残念ながら、CoffeeScript は、非同期コードが関係するこの種の問題にはあまり役に立ちません (より簡潔な関数構文を使用することは別として、これは実際には非常に優れています)。
results
あなたのコードは機能しますが、小さな注意点が 1 つあります。配列内の値の順序が、 sources
. setTimeout
と乱数を使用して、予期しない非同期動作を取得する小さな作業スニペットを次に示します。
calculateValues = (sources, callback) ->
counter = 0
length = sources.length
result = []
for source in sources
source.readValue (value) ->
result.push value
counter++
callback result if counter is length
sources = for i in [1..5]
do (i) ->
readValue: (cb) ->
setTimeout (-> cb "Value #{i}"), Math.random() * 1000
calculateValues sources, (results) ->
console.log "results", results
jsフィドル
出力例:
results ["Value 2", "Value 5", "Value 1", "Value 3", "Value 4"]
順序を維持したい場合、それは非常に簡単な修正ですが、これは、非同期コードを正しく取得することがいかに難しいかを示しています。
幸いなことに、他のツールを使用してこの種の構造を表現するより良い方法があります。Async.jsのような単純なライブラリを使用して同期を支援することをお勧めします。以下は、使用するために書き直された同じスニペットasync.parallel
と、次の形式の 2 つの引数のコールバックを使用するという Node の規則ですfunction(err, value)
(また、Underscore.js のちょっとしたヘルプもあります。必要ない場合は、ネイティブ CS に非常に簡単に変換できます)。
calculateValues = (sources, callback) ->
funcs = _.pluck sources, 'readValue'
async.parallel funcs, callback
sources = for i in [1..5]
do (i) ->
readValue: (cb) ->
setTimeout (-> cb null, "Value #{i}"), Math.random() * 1000
calculateValues sources, (err, results) ->
console.log "results", results
jsフィドル
出力:
results ["Value 1", "Value 2", "Value 3", "Value 4", "Value 5"]