39
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Promiseの直列処理をループする(完了後に実行したい処理もある)

Posted at

はじめに

JavaScriptでPromiseを使い始めたとき、出来ると便利な以下の場合について。

  • Promiseで順番に実行する直列処理を、ループで繰り返す
  • ループ完了後に実行したい処理がある。

Promiseをループで繰り返す

まず最初に、Promiseの処理をforループで繰り返す基本パターン。

// Promiseの処理をループで繰り返す
var myPromise = Promise.resolve();
for(var i = 0; i < 3; i++) {
  myPromise = myPromise
  .then(task1.bind(this, i)) // bindでtask1に引数iを渡す
}


// ループで実行する処理
function task1(val){ // 引数iを受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task1 : ' + val);
        resolve();
     }, 1000);
  });
}
実行結果
task1 : 0
task1 : 1
task1 : 2

実行パターン

直列処理を繰り返す

メソッドチェーンでつないだ、Promiseの直列処理をループで繰り返すパターン。

// Promiseの直列処理をループで繰り返す
var myPromise = Promise.resolve();
for(var i = 0; i < 3; i++) {
  myPromise = myPromise
  .then(task1.bind(this, i)) // bindでtask1に引数iを渡す
  .then(task2)
}


// ループで実行する処理
function task1(val){ // 引数iを受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task1 : ' + val);
        resolve(val); // task2へ値を渡す
     }, 1000);
  });
}

function task2(res){ // task1から値を受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task2 : ' + res);
        resolve();
     }, 1000);
  });
}
実行結果
task1 : 0
task2 : 0
task1 : 1
task2 : 1
task1 : 2
task2 : 2

ループ完了後に実行

メソッドチェーンでつないだ、Promiseの直列処理をループで繰り返し、ループ完了後に処理を実行する。

// Promiseの直列処理をループで繰り返す
var myPromise = Promise.resolve();
for(var i = 0; i < 3; i++) {
  myPromise = myPromise
  .then(task1.bind(this, i)) // bindでtask1に引数iを渡す
  .then(task2)
}
myPromise
.then(function(){
  return new Promise(function (resolve, reject) {
    // ループ完了後に実行したい処理
    console.log('ループ完了後に実行');
    resolve();
  });
})


// ループで実行する処理
function task1(val){ // 引数iを受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task1 : ' + val);
        resolve(val); // task2へ値を渡す
     }, 1000);
  });
}

function task2(res){ // task1から値を受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task2 : ' + res);
        resolve();
     }, 1000);
  });
}
実行結果
task1 : 0
task2 : 0
task1 : 1
task2 : 1
task1 : 2
task2 : 2
ループ完了後に実行

ループで繰り返す処理をまとめる

ループで繰り返す直列処理task1()task2()taskAll()にまとめたパターン。
実行結果は同じです。

// Promiseの直列処理をループで繰り返す
var myPromise = Promise.resolve();
for(var i = 0; i < 3; i++) {
  taskAll(i);
}
myPromise
.then(function(){
  return new Promise(function (resolve, reject) {
    // ループ完了後に実行したい処理
    console.log('ループ完了後に実行');
    resolve();
  });
})


// ループで実行する処理
function taskAll(i){
  myPromise = myPromise
  .then(task1.bind(this, i)) // bindでtask1に引数iを渡す
  .then(task2)
}

function task1(val){ // 引数iを受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task1 : ' + val);
        resolve(val); // task2へ値を渡す
     }, 1000);
  });
}

function task2(res){ // task1から値を受け取る
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
        console.log('task2 : ' + res);
        resolve();
     }, 1000);
  });
}
実行結果
task1 : 0
task2 : 0
task1 : 1
task2 : 1
task1 : 2
task2 : 2
ループ完了後に実行

taskAll()に直列処理だけではなく、Promise.all()で並列処理を組み合わせることも出来ます。

おわりに

他にも使いそうな便利なパターンがあれば追記します。

※ 直列処理や引数の扱いについては、Promiseとthenのメソッドチェーン(直列・並列・値の受け取り・引数)を参照。

39
26
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
39
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?