263
262

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.

JavaScriptのasync.jsでwaterfallとseries、parallelの違い

Last updated at Posted at 2013-08-07

#async.js
主にnodeで使用されている、javascriptの非同期処理を扱うライブラリです。
フロントエンドでもゲーム作り等では重宝するんです。

その中でも使用率がかなり高い、waterfallとseries、そしてparallelの三つについて簡単にまとめました。

さらに、ECMAScript6からは非同期処理を扱うためのPromiseオブジェクトが標準で使用できます。
ECMAScript6のアロー関数とPromiseまとめ - JavaScript

技術情報のみつぶやくアカウント作成しました。JavaScriptなどの最新情報も追っていきます。
Twitter: [@takeharumikami]
(https://twitter.com/takeharumikami)

RSSはこちら
Feedly: [Feedlyをフォロー]
(http://cloud.feedly.com/#subscription%2Ffeed%2Fhttp%3A%2F%2Fqiita.com%2Ftakeharu%2Ffeed)
RSS: http://qiita.com/takeharu/feed

#waterfall

まず、waterfallについてです。
配列の順番で、この場合は上の関数から実行されていきます。

この際に引数に与えられたcallbackの関数が実行されるまで、
次の関数の処理には移行しません。

そしてcallbackの関数の第一引数にはerrorを、
第二引数以降は次の関数に渡したい引数を選ぶ事ができます。

async.waterfall([
  function(callback) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      callback(null, 1);
    }, 100);
  },
  function(arg1, callback) { // arg1 === 1
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      callback(null, 1, 2);
    }, 50);
  },
  function(arg1, arg2, callback) { // arg1 === 1, arg2 === 2
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      callback(null, 1, 2, 3);
    }, 10);
  }
], function(err, arg1, arg2, arg3) { // arg1 === 1, arg2 === 2, arg3 === 3
  if (err) {
    throw err;
  }
  console.log('all done.');
  console.log(arg1, arg2, arg3);
});

//出力結果
1
1 done
2
2 done
3
3 done
all done
1 2 3

#series

seriesの流れはwatarfallの制御の流れと同じです。

配列の順番に、この場合は上から順次実行されていきます。
そして、次の関数に処理が移るにはcallbackが呼ばれる必要があります。

違いはcallbackの引数に渡した値ですが、
最後にまとめてこの配列の順番のまま、配列に値が代入されています。

async.series([
  function(callback) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      callback(null, 1);
    }, 100);
  },
  function(callback) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      callback(null, 2);
    }, 50);
  },
  function(callback) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      callback(null, 3);
    }, 10);
  }
], function(err, results) {
  if (err) {
    throw err;
  }
  console.log('all done');
  console.log(results);
});

//出力結果
1
1 done
2
2 done
3
3 done
all done
[1, 2, 3]

#parallel

最後にparallelです。
seriesやwaterfallと違い、並列に処理されます。
(厳密には並列ではないですが)

ですから引数に渡されたcallbackでは次の関数が呼ばれません。

callbackに渡した引数はまとめて最後に配列となって、
この順番通りに代入されています。

async.parallel([
  function(callback) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      callback(null, 1);
    }, 100);
  },
  function(callback) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      callback(null, 2);
    }, 50);
  },
  function(callback) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      callback(null, 3);
    }, 10);
  }
], function(err, results) {
  if (err) { 
    throw err;
  }
  console.log('all done');
  console.log(results);
});

//出力結果
1
2
3
3 done
2 done
1 done
all done
[1, 2, 3] 

parallelは並列処理なので、
配列に関数を代入しなくてもいいです。

そこで別パターンとしてオブジェクトの各valueに関数を代入する方法があります。

この場合の違いは二点です。

1:並列処理の開始が保証されない
2:callbackに渡した値が、最後にまとめてオブジェクトに代入されている

1は配列の時と違い、どこから実行されるか保証されていないということです。
配列のときは要素の0から実行されていきます。

2は下記を見てもらえればわかるのですが、
同じkeyに対応して渡された値が代入されています。

async.parallel({
  first: function(callback) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      callback(null, 1);
    }, 100);
  },
  second: function(callback) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      callback(null, 2);
    }, 50);
  },
  third: function(callback) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      callback(null, 3);
    }, 10);
  }
}, function(err, results) {
  if (err) { 
    throw err;
  }
  console.log('all done');
  console.log(results);
});

// 出力結果
1
2
3
3 done
2 done
1 done
all done
{ third: 3, second: 2, first: 1 }

まとめ

コールバック処理はjavascriptでは重要な要素ですよね。

asyncを使うとスパゲッティにもなりづらいですし、
うまく扱えるとかなり重宝しますので、ぜひぜひおすすめです。

アカウント

技術情報のみつぶやくアカウント作成しました。JavaScriptなどの最新情報も追っていきます。
Twitter: [@takeharumikami]
(https://twitter.com/takeharumikami)

RSSはこちら
Feedly: [Feedlyをフォロー]
(http://cloud.feedly.com/#subscription%2Ffeed%2Fhttp%3A%2F%2Fqiita.com%2Ftakeharu%2Ffeed)
RSS: http://qiita.com/takeharu/feed

おすすめの記事

ECMAScript6からは非同期処理を扱うためのPromiseオブジェクトが標準で使用できます。
ECMAScript6のアロー関数とPromiseまとめ - JavaScript

入門者がつまづく、thisの挙動を4種類に分けて簡単に学ぶならこれ。Apply, callの挙動までわかる。
JavaScriptの「this」は「4種類」?」

JavaScriptでは関数型言語の一部の機能?実践的なJavaScriptの関数型とは。
JavaScriptで関数型プログラミングの入門

263
262
1

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
263
262

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?