JavaScript
Node.js

Async.js は自動的に非同期処理や並列処理にしてくれるライブラリじゃないよ

More than 5 years have passed since last update.

誤解されてそうなので注意書き。


検証例


async-test.coffee

require "async"

bigArray = (() ->
arr = []
i = 0
while(i < 1e+6)
arr[i] = i + 1
i = i + 1
arr
)()

async.parallel
task1: (callback) ->
console.log "task1: start"
async.map bigArray
, (v, next) ->
next null, v * 2
, (error, result) ->
console.log "task1: done"
callback error, result
task2: (callback) ->
console.log "task2: start"
async.map bigArray
, (v, next) ->
next null, v * v
, (error, result) ->
console.log "task2: done"
callback error, result
, (error, result) ->
console.log "=== async test done ==="

console.log "=== async test start ==="



ライブラリが非同期処理や並列処理をやってくれてるならこういう出力のはず


expect-log.txt

$ coffee async-test.coffee

=== async test start === # すぐに出るはず
task1: start # すぐに出るはず
task2: start # すぐに出るはず
task1: done # やや遅れて出るはず
task2: done # ほぼ task1 の終了と同時にでるはず
=== async test done === # すべて終わってから出るはず


実際の実行後の出力


log.txt

$ coffee async-test.coffee

task1: start # あれ、テスト開始の出力より先に出た…
task1: done # けっこう待たされた
task2: start # task1 が終わってから出力された? parallel って API なのに…
task2: done # やっぱり待たされた
=== async test done === # これはまあよし
=== async test start === # えっ今ごろ


解説

ソース読めばわかりますが、async.nextTick と、内部でそれを利用している


  • async.waterfall

  • async.queue

以外の API は process も Timer オブジェクトも使用していません。

なので、普通に


  • setTimeout

  • process.nextTick

  • node.js の非同期API

  • XHR はじめとした Ajax API

これらを使わない限り、一つ一つの処理を順番に処理しますし、async.* の呼び出した処理が終わるまで次の処理に進みません。


「えっじゃあなんで Async だとか言ってるの」

Async.js は別に渡した関数を非同期、並列処理化するものではなく、単純に継続渡し形式(CPS) でリストイテレータや処理のワークフローの為のユーティリティを提供しているだけです。

node.js の非同期API群(あれも実際はノンブロッキングでも非同期なんかでもない)を利用する際に「CPS なユーティリティ API を使えたらラクができるよね、非同期プログラミングのスタイルでやれるよね」といったモノであると考えた方がよく、

ユーザー側が setTimeoutprocess.nextTick 等々で処理をラップしたら、そこで「非同期処理や並列処理っぽい」振る舞いをしてくれるライブラリです。

また、並列処理のように見えるだけで "並列処理" ではありません。

名前に偽りありだと思うけどね…