javascript - 关于通过 let 声明变量的变量范围的疑问

标签 javascript asynchronous ecmascript-6

以我的观点,我在一本书中遇到了奇怪的断言。我想我有些不明白,但无论如何,如果您能说明情况,那就太好了。

ajax('<host1>/items',                                       
   items => {
   for (let item of items) {
      ajax(`<host2>/items/${item.getId()}/info`,            
      dataInfo => {
        ajax(`<host3>/files/${dataInfo.files}`,            
           processFiles);
   });
  }
});

作者关注:

There’s another hidden problem with this code. Can you guess what it is? It occurs when you mix a synchronous artifact like a for..of imperative block invoking asynchronous functions. Loops aren’t aware that there’s latency in those calls, so they’ll always march ahead no matter what, which can cause some really unpredictable and hard-to-diagnose bugs. In these situations, you can improve matters by creating closures around your asynchronous functions, managed by using forEach() instead of the loop.

取而代之的是,他们提供了以下内容:

ajax('/data',                            
  items  => {                            
     items.forEach(item => {
    // process each item             
 });

});

坦率地说,我希望如果我们使用 let for 循环,这意味着我们为每次迭代创建一个闭包,因此我看不到任何隐藏的问题。

最佳答案

你是对的,如果作者的评论是针对那个确切的代码片段,那他们就错了。

Loops aren’t aware that there’s latency in those calls [...] you can improve matters by [...] using forEach()

这没有任何改变,forEach() 同样不知道其回调内部进行的异步调用,因为 for 循环是在其主体中进行的异步调用。 forEach() 将“始终向前推进”,就像 for 循环一样。

使用 let 就不会遇到作者担心的问题,因为循环的每次迭代都有自己的 item 就像使用 一样items.forEach( item => { ... .

即使使用 var,该代码也没有问题,因为变量 item 没有在 ajax 请求的回调中使用。您可以通过在回调中使用 var 和使用 item 来产生作者的关注,例如:console.log( item.getId() );.

注意:重要的是要注意回调很可能会以与它们启动时不同的顺序(看似随机的)运行。如果您不知道它可能会导致令人惊讶的错误,但它也有与使用循环还是使用 forEach 无关。

关于javascript - 关于通过 let 声明变量的变量范围的疑问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48174506/

相关文章:

javascript - 如何在 ng-click 上使用面包屑?

javascript - 定位 window.location.pathname

javascript - 更改同一字段中的日期颜色和日期格式

c# - 使用 Rx Framework 使用 void AsyncMethod(Action<T>callback) 模式进行异步调用

javascript - 如何在列表项上切换事件类?

javascript - Lodash fp(函数式编程)减少不工作我期望它如何工作

javascript - 同步函数在异步函数中的影响

c++ - 如何执行异步离屏查询?

javascript - ES6 在循环之前或循环中声明变量

javascript - ReactJS - 谁能解释一下这个状态是如何以及为什么被改变的?