asynchronous调用NodeJS中的asynchronous响应
我现在正在用NodeJS构build我的第一个项目,但是我对这个任务有点困惑,我认为这是一个简单的问题,我想问题是我对这些asynchronous方法缺乏了解,但是我无法在任何地方find答案。
我有一个简单的循环遍历数组和任何元素,根据一些规则,我会调用一个函数或另一个。 现在一些操作会比其他操作更快,所以我最终可能会返回元素N上的函数,而不是元素N-1上的函数。 为了使它像这样简单
for (var i = 0 ; i < 10 ; i++) { if (i%2 === 0) { setTimeout(function(i) { console.log(i); }, 2000); } else { console.log(i); } }
所以任何偶数都会打印2秒,而奇数将被立即打印。 无论如何,运行它我得到
1 3 5 7 9 <<2 seconds break>> undefined undefined undefined undefined undefined
看起来偶数值是“迷失”。 我怎样才能通过这个值确保函数不会丢失input值? 我错过了什么吗?
谢谢,毛罗
你的setTimeout
参数函数被声明为一个参数, i
。 当setTimeout
调用没有参数的函数时,参数被设置为undefined
。
这似乎是稍微好一点,因为它不再影响你最初试图引用的外部variables…
setTimeout(function() { console.log(i); }, 2000)
…但如果你运行它,你会发现它打印10
5次,因为你创build的每个函数引用相同的i
variables,当循环退出条件变为true
并且它终止时,它的值将是10
。
创build一个闭包 ,它保存了i
在创buildsetTimout
参数函数的循环过程中的值,
setTimeout((function(i) { return function() { console.log(i); } })(i), 2000)
将参数重命名为我们刚刚使用的“ 立即调用函数expression式”可能有助于使事情变得更加清晰:
setTimeout((function(loopIndex) { return function() { console.log(loopIndex); } })(i), 2000)
我们是:
- 创build一个接受一个参数并返回另一个函数的函数。
- 立即调用“外部”函数,传递它的当前值(这不是一个对象,所以有效地通过值)。
- “外部”函数返回“内部”函数,它作为parameter passing给
setTimeout
。
这是因为:
-
在JavaScript中创build一个函数会创build一个新的范围来保存函数的参数variables以及其中使用
var
关键字在其中声明的任何其他variables。 把它想象成一个不可见的对象,其属性对应于variables名称。 -
作为其范围链的一部分,所有函数都会引用它们被定义的范围 。 他们仍然可以访问这个范围,即使它不再是“活动”(例如,当它为返回创build的function)。 “内部”函数是在包含一个
loopIndex
variables的范围内创build的,该variables设置为在调用IIFE时的值。 所以当你试图从内部函数中引用一个名为loopIndex
的variables时,它首先检查自己的作用域(并且没有find一个loopIndex
), 然后开始向上遍历它的作用域链 – 首先,它检查它的作用域定义,它包含一个loopIndex
variables,其值被传递给console.log()
。
这就是一个闭包 – 一个函数可以访问定义的范围,即使范围被创build的函数已经执行完毕。
尽pipe通常使用bind
来确保callback函数内部的值是您想要的值,但您也可以使用它来修改传递给绑定函数的参数。 在你的情况下,代码可能看起来像这样(我改变了一些variables的名称,所以它是更清楚发生了什么事情):
for (var i = 0 ; i < 10 ; i++) { if (i % 2 === 0) { setTimeout(function(num) { console.log(num); }.bind(this, i), 2000); } else { console.log(i); } }
在这种情况下,该函数具有.bind(this, i)
附加到它。 this
只是填充; bind
的第一个参数始终是你想要在绑定函数内parsing的内容。 然后,我们可以传入任何我们希望添加到绑定函数参数中的值 – 在这种情况下,我们希望将当前值(当函数绑定时)传递给函数。
您可以在MDN文档中阅读有关bind
更多信息。
setTimeout(function(i) { console.log(i); }, 2000);
从setTimeout调用的函数不会被任何参数调用。 你需要创build一个闭包。
看看这个问题和接受的答案。
(这不是一个node.js特定的问题)