Skip to content
Tags

Promiseを使った非同期ループ処理の書き方について

by : 2016/02/22

JavaScriptで常に頭を悩ませるのが非同期処理ではないかと思います。非同期処理を幾つも実行したりすると、思ったタイミングで処理が走らないといったことが多々あります。

そんな中でループ処理になると、特に厄介ではないでしょうか。そこで今回はPromiseを使ったループ処理について紹介します。

0から10まで順番に処理をしたら抜けるループ

非同期処理でない場合は次のように書けます。

for (var i = 0; i <= 10; i++) {
  console.log(i)
}
console.log(“Finish”);

厄介なのは非同期処理時です。まず、基本形として次のようにPromiseを考えます。

new Promise(function(res, rej) {
 
}).then(function() {
  console.log(“Finish”);
})

この処理は一瞬で終了してしまいます。コンソールにも特に何もメッセージは出ません。この中でループ処理を行うようにします。この時、注意するのは非同期処理がターゲットと言うことです。そのため、loop関数の中でもPromiseを使って処理を行うようにして、処理順番を保証します。

new Promise(function(res, rej) {
  function loop(i) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log(i);
            resolve(i+1);
        }, 100);
    })
  }
  loop(0);
}).then(function() {
  console.log(“Finish”);
})

これにより、非同期処理(setTimeout)が実行された後、resolveが実行されるようになります。後は内側のPromiseについて、then処理を書きます。

// ループ処理の完了を受け取るPromise
new Promise(function(res, rej) {
  // ループ処理(再帰的に呼び出し)
  function loop(i) {
    // 非同期処理なのでPromiseを利用
    return new Promise(function(resolve, reject) {
      // 非同期処理部分
      setTimeout(function() {
        console.log(i);
        // resolveを呼び出し
        resolve(i+1);
      }, 100);
    })
    .then(function(count) {
      // ループを抜けるかどうかの判定
      if (count > 10) {
        // 抜ける(外側のPromiseのresolve判定を実行)
        res();
      } else {
        // 再帰的に実行
        loop(count);
      }
    });
  }
  // 初回実行
  loop(0);
}).then(function() {
  // ループ処理が終わったらここにくる
  console.log(“Finish”);
})

thenの中で処理判定を行い、ループを抜けるかどうかの判定を行っています。これで非同期処理における処理順番の保証と、処理完了時に次の処理につながる部分ができました。


JavaScriptにおける非同期処理のループはかなり面倒であるというのが分かるかと思います。JSDoc: Namespace: asyncを使うと非同期処理におけるループがこれくらい分かりやすく書けるようになります。以下は処理を5回繰り返すという指定です。

var loop = h5.async.loop(new Array(5), function (i, v) {
  var deffered = h5.async.deferred();
  var loop = function (count) {
    setTimeout(function () {
      console.log(count);
      deffered.resolve(count);
    }, 100);
  };
  loop(i);
  return deffered.promise();
}).done(function () {
  console.log(“処理完了”);
});

From → hifive, HTML5

コメントは停止中です。

%d人のブロガーが「いいね」をつけました。