LoginSignup
110
101

More than 5 years have passed since last update.

for文の中で非同期関数を使いたいときでも慌てずPromiseする

Posted at
for (var i = 0; i < takusan; i++) {
    omotai(i, function () {
        おやっ
    });
}

これコールバックの中のものどうやって取るんだ?(だいたい無理)

Promiseが使える環境なら、迷わず書けます。
予めPromise化しておくと便利です。bluebirdなどPromise化を助けてくれるライブラリを使うのもいいでしょう。

function omotaiPromise(arg) {
    new Promise(function (resolve, reject) {
        omotai(arg, function (err, result) {
            if (err != null) {
                reject(err);
                return;
            }
            resolve(result);
        });
    });
}

で、こう。

var promises = [];
for (var i = 0; i < takusan; i++) {
    promises.push(omotaiPromise(i));
}
Promise.all(promises)
    .then(function (results) {
        // results配列の各要素で結果が取れる
    });

Promise.allを使うのがキモですね。


別のケース

for (var i = 0; i < list.length; i++) {
    if (list[i].conditionSync() === 'good') {
        list[i].workHardSync();
    }
}

これを非同期化する場合はどうでしょう。

まあまずfilterとかforEachとか使えって話ですね。

list.filter(function (x) { return x.conditionSync() === 'good'; })
    .forEach(function (x) { x.workHardSync(); });

で、これのPromise版

Promise
    .all(list.map(function (x) { return x.condition(); }))
    .then(function (conds) {
        Promise.all(
            list.filter(function (v, i) { return conds[i]; })
                .map(function (x) { return x.workHard(); }));

listがかっちりしていればmapが大活躍します。

functionだらけでみにくいですね。Promiseを使うときはTypeScriptbabelを使うと良いでしょう。

Promise
    .all(list.map(x => x.condition()))
    .then(conds =>
        Promise.all(
            list.filter((v, i) => conds[i])
                .map(x => x.workHard()));

ね、簡単でしょう?

110
101
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
110
101