3

オブジェクトの配列があり、それぞれに非同期readValue関数があり、コールバックをパラメーターとして受け入れ、このオブジェクトの値が利用可能になったときに起動されるとします。

私の目標は、各オブジェクトのすべての値を計算し、それらの値を含む配列を返すことです。

最初に頭に浮かんだのはこれ

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

メソッドは非同期であるためreadValue、それを呼び出す関数も非同期です。すべての値がresult配列になると、callback関数が実行されます。

しかし、これはすべて面倒に思えます。これは、coffeescript が本当に強力な領域です。内包表記が少ないコードでもこの関数を書くことは可能ですか? 同期であればOKです。

4

1 に答える 1

0

残念ながら、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"]
于 2013-04-18T06:19:51.837 に答える