围绕承诺的for循环中的词法范围?

时间:2014-06-04 03:32:41

标签: javascript coffeescript scope promise lexical-scope

我有一个ids对象,可将id个字符串映射到product个对象。

for id of ids
  product = ids[id]
  console.log product # Prints out something different each loop. :)
  Product.create(product).then ->
    console.log product # Only prints out the last id each loop. :(

我正在使用库进行数据库交互,这会暴露承诺(由上面的then函数指示)。我正在尝试在product函数中打印出then变量,但我似乎只是在id中获得了最后一个ids,所以它看起来像是范围问题。如何正确确定product变量的范围,以便在每个循环的then函数中打印出不同的产品?

2 个答案:

答案 0 :(得分:2)

@false找到了right duplicate describing your issue。实际上,您已经遇到了一个范围问题,其中product对于循环体是非本地的,并且您只从异步回调中获得最后一项。

  

如何正确调整产品变量的范围,以便在当时的回调中打印出不同的产品?

在惯用的coffeescript中,你将在循环中使用do notation作为IEFE:

for id of ids
  do (product = ids[id]) ->
    console.log product
    Product.create(product).then ->
      console.log product

或者,直接从of循环绘制属性值:

for id, product of ids
  do (product) ->
    …

答案 1 :(得分:2)

Bergi的代码误导IMO,因为它一次运行整个循环,而不是顺序运行。出于这个原因,我只需要将所有代码提升到promises中,而不是混合同步和异步:

Promise.resolve(product for _, product of ids).then next = (products) ->
  [product, products...] = products
  if product
    console.log product
    Product.create(product).then ->
      console.log product
      next products
.then ->
  console.log "all done"

区别在于:

  • 就像在一个真实的循环中一样,下一个项目不会运行直到上一个完成
  • 就像在一个真实的循环中一样,下一行(仅需要then ->才能在循环完全完成后运行

真实循环的这些属性比表面语法重要得多,您可以在几天内学习。

让它运行并查看日志中的差异。