我对Coffeescript的预期行为有疑问。这是一个错误吗?
通过for循环映射列表的元素并再次将它们取出是没有问题的。
idList = [0, 1, 999]
results =
for id in idList
id
console.log results # prints [ 0, 1, 999 ]
现在,让我们再次将它们包含在承诺中。这打破了。
查看代码是最好的解释。
idList = [0, 1, 999]
operations =
for id in idList
new Promise (resolve, reject) -> resolve()
.then -> id
Promise.all operations
.then (results) ->
console.log results # prints [ 999, 999, 999 ]
你会认为for循环行(第3行)中的 id 是在该范围内声明的。
idList = [0, 1, 999]
operations =
idList.map (id) ->
new Promise (resolve, reject) -> resolve()
.then -> id
Promise.all operations
.then (results) ->
console.log results # prints [ 0, 1, 999 ]
当从for循环中的promise内部返回变量并检查已编译的Javascript代码时,我们可以看到Coffee编译器已在外部作用域声明了该变量,因此返回的值成为最后一个值变量,总是。
var id, idList, operations; # id is declared here
idList = [0, 1, 999];
operations = (function() {
var i, len, results1;
results1 = [];
for (i = 0, len = idList.length; i < len; i++) {
id = idList[i];
results1.push(new Promise(function(resolve, reject) {
return resolve();
}).then(function() {
return id;
.......
这是真的有意,是一个错误,还是一个需要注意的警告?
CoffeeScript版本2.1.1 节点版本v9.7.1
答案 0 :(得分:0)
你的第三个猜测是正确的 - 需要注意的是它需要注意的事项。
这是预期的行为,是Javascript和Coffeescript中常见的错误来源。
变量在循环内的顶部作用域中指定。如果要在循环中定义函数或承诺,它们都将引用相同的变量。如果在循环移动后执行函数/ promise,则变量不会包含您期望的内容。要解决这个问题,请使用Coffeescript中的do
运算符,该运算符将编译为Javascript中立即执行的匿名函数。
在do
示例中使用Promise
运算符:
idList = [0, 1, 999]
operations =
for id in idList
do (id) ->
new Promise (resolve, reject) -> resolve()
.then -> id
查看loops and comprehensions section:
末尾的官方文档当使用JavaScript循环生成函数时,通常会插入一个闭包装,以确保循环变量被关闭,并且所有生成的函数不只是共享最终值。 CoffeeScript提供
do
关键字,它立即调用传递的函数,转发任何参数。