2012-01-27 99 views
2

有没有一种优雅的方式异步映射对象或数组在coffeescript? (或JavaScript)coffeescript异步映射

想象我有一些事情在一个对象:

things = 
    x: 
    ... 
    y: 
    ... 
    z: 
    ... 

thingCount = 3 

我希望创建一个将各处理这些事情,并返回处理对象的方法。该进程必须进行异步调用以获取有关每个事物的一些信息。 一开始我尝试只是为了遍历性,像这样:

processThings = (callback) -> 

    processedThings = {} 
    count = 0 

    for key,val in things 

    asyncJob key,val (err,result) -> 

     if err 
     callback error 
     else 
     # PROBLEM: key has the incorrect value here 
     processedThings[key] = result  
     count += 1 
     if count == thingCount 
      callback null,processedThings 

的问题是,在循环键的值更改。所以我的解决办法是,这样的关键变量包含在其闭包内创建一个子功能:

processThings = (callback) -> 

    processedThings = {} 
    count = 0 

    processThing = (key,val) -> 

    asyncJob key,val (err,result) -> 

     if err 
     callback error 
     else 
     processedThings[key] = result  
     count += 1 
     if count == thingCount 
      callback null,processedThings 

    processThing key,val for key,val of things 

但男孩你好这肯定是的fugly。是否有这样的首选模式?

+1

使用[图效用](https://github.com/Raynos/after.js/blob/master/src /after.js#L64) – Raynos 2012-01-28 00:08:56

+0

“后”看起来像一个很好的图书馆雷诺斯 - 谢谢! – mainsocial 2012-01-28 19:35:57

回答

5

的CoffeeScript覆盖此与do关键字,在Loops and Comprehensions结束描述:

当使用JavaScript循环来生成功能,它是常见的,以确保该循环变量被关闭,以插入一个封闭的包装并且所有生成的函数不仅仅共享最终值。 CoffeeScript提供了do关键字,该关键字立即调用传递的函数,转发任何参数。

for filename in list 
    do (filename) -> 
    fs.readFile filename, (err, contents) -> 
     compile filename, contents.toString() 

它可以应用到您的代码:

processThings = (callback) -> 

    processedThings = {} 
    count = 0 

    for key,val in things 

    # add this to close over `key` 
    do (key) -> 

     asyncJob key,val (err,result) -> 

     if err 
      callback error 
     else 
      processedThings[key] = result  
      count += 1 
      if count == thingCount 
      callback null,processedThings 
+0

美丽,谢谢乔纳森!这是javascript的一个滑溜溜的部分。 – mainsocial 2012-01-28 19:33:19