是否可以通过coffeescript理解从回调中收集结果?

是否可以通过coffeescript理解从回调中收集结果?,coffeescript,list-comprehension,for-comprehension,Coffeescript,List Comprehension,For Comprehension,假设我有一个对象数组,每个对象都有一些异步的readValue函数,它接受callback作为它的参数,当这个对象的值可用时,它将被激发 我的目标是计算每个对象的所有值,并用这些值返回数组 我首先想到的是这个 calculateValues = (sources, callback) -> counter = 0 length = sources.length result = [] for source in sources source

假设我有一个对象数组,每个对象都有一些异步的
readValue
函数,它接受callback作为它的参数,当这个对象的值可用时,它将被激发

我的目标是计算每个对象的所有值,并用这些值返回数组

我首先想到的是这个

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
方法是异步的,所以调用它的函数也是异步的。当所有值都在
结果
数组中时,将执行
回调
函数


但我觉得这一切都很混乱。这就是coffeescript真正强大的领域。即使代码不那么复杂,也能编写这个函数吗?如果它是同步的,那没关系。

不幸的是,CoffeeScript在处理这些涉及异步代码的问题时帮不了你多少忙(除了有一个更简洁的函数语法,实际上这很好)

您的代码可以工作,但有一点需要注意:
结果
数组中的值顺序与
中的源顺序不匹配。下面是一个小的工作片段,它使用
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

样本输出:

结果[“值2”、“值5”、“值1”、“值3”、“值4”]
如果您想保留顺序,这是一个非常简单的修复程序,但这说明了正确获取异步代码是多么棘手

幸运的是,在其他工具的帮助下,有更好的方法来表达这种构造。我建议使用一个简单的库来帮助同步。下面是重写的相同代码段和Node的约定,即使用
函数(err,value)
的两个参数回调(还有一点下划线.js小帮助,如果不需要,可以很容易地将其转换为本机CS):

输出:

结果[“值1”、“值2”、“值3”、“值4”、“值5”]
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