我很难理解为什么let
在JavaScript中的异步循环中起作用。
我正在使用异步功能从数据库中进行各种插入和检索
我的代码看起来像这样:
for (var i = 0; i < row.length; i++) {
pool.query(`Select Name from Students where ID = ${row[i].PartID}`)
.then(rows => {
....
....
}
该数组从最大i
值而不是row[i]
中的0开始。我了解自己做错了什么,但是当我寻找解决方案时,发现使用let
而非var i
可以解决此问题。
但是我不明白为什么会这样。为什么使用let
阻止变量i
在异步函数执行之前增加?
答案 0 :(得分:0)
var
具有功能范围。
let
具有阻止范围。
因此,在这样的for
循环中:
for (let i = 0; i < row.length; i++)
循环的每个迭代都有其自己的单独的i
变量。在循环内使用异步操作时,这会将每个单独的i
变量保留为自己的异步回调,因此一个变量不会覆盖另一个变量。
由于var
是函数范围的,因此在执行此操作时:
for (var i = 0; i < row.length; i++)
整个函数中只有一个i
变量,并且for
循环的每个迭代都使用相同的变量。 for
循环的第二次迭代更改了i
的值,第一次迭代中的任何异步操作都可能尝试使用该值。如果这些异步操作试图在异步回调中使用其i
的值,则可能导致问题,因为与此同时for
循环将对其进行更改。
这是一个经典的例子:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 10);
}
而且,现在有了let
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 10);
}
运行每个并查看结果差异。在两个示例中,for
循环运行完成并调度5个计时器。在var
示例中,所有计时器回调都从现已完成的i
循环中看到一个for
变量,因此它们都将5
输出为{{1}的值}。
在i
示例中,循环的每次迭代都有其自己的let
变量,不受i
循环进行的影响,因此在调用其计时器回调时( for
循环完成),它们仍然具有与for
循环的迭代最初执行时所具有的i
相同的值,因此它们输出期望的递增序列。
答案 1 :(得分:-1)
我要看的一件事是for循环的每个迭代是否正在等待异步函数解析。在您连接到数据库并执行操作之前,它可能一直持续运行。这就是为什么它从max开始的原因。
除此之外,尚不清楚即使在here.中显示了新的块范围规则的情况下,为什么仍要使用'let'还是很重要