[Javascript] ある条件が満たされるまでループする

  • 1
    Like
  • 0
    Comment

例えば、あるライブラリlib.jsを読み込んだ後にそのライブラリの関数funcに引数[1, 2]を入れて実行したいとする。
その場合以下のように書けばよい。

<!-- 読み込み終わると、グローバル変数 MYLIB にライブラリが代入されるものとする -->
<script async src="lib.js">

<script>
(function loop(args, interval) {
    if(typeof MYLIB !== "undefined") { // ループを抜ける条件を入れる
        return MYLIB.func(args); // func(args); return true; などと書いてもいい
    }
    setTimeout(loop, interval, args);
})([1, 2], 100); // 100ミリ秒ごとにチェックする
</script>

これを一般化すると以下のようになる。

(function loop(args, interval) {
    if(condition) { // ループを抜ける条件を入れる
        return func(args);
    }
    setTimeout(loop, interval, args);
})();

さらに一般化を進め、任意の関数を条件達成後に実行する関数は以下となる。

/**
 * 100ミリ秒毎にライブラリの読み込みが終わったかチェックし、その後関数funcを実行するループを作成する。
 * @param {function} func      ループを抜ける際に実行される関数 
 * @param {function} condition ループを抜ける条件。この関数は true か false を返さなければならない
 * @param {array}    args      func に適用される引数の配列
 * @param {number}   interval  ループする感覚(ミリ秒)
 */
let makeLoop = (func, condition = () => {return true}, args = [], interval = 100) => {
    (function loop() {
        if(condition() === true) {
            return func(args)
        }
        setTimeout(loop, interval, args);
    })();
};


// 読み込み終わると、グローバル変数 MYLIB にライブラリが代入されるものとする
$.getScript("lib.js");

let [f, c, a, i] = [
    (args) => { MYLIB.func(args) }, // Uncaught ReferenceError を回避するため
    () => {
        return typeof MYLIB !== "undefined";
    },
    [1, 2],
    100
];

makeLoop(f, c, a, i); // MYLIB に値が代入された後100ミリ秒以内に MYLIB.func([1, 2]) が実行される