Javascript 这个for循环如何无序地执行其迭代器?

Javascript 这个for循环如何无序地执行其迭代器?,javascript,node.js,Javascript,Node.js,我在async函数中使用for循环,循环中包含wait。从我读到的内容来看,for循环应该可以很好地处理await,但似乎有一些不寻常的行为我不理解 考虑所描述的func,将其简化为场景的基本要素: let counter = 0; module.exports = async () => { console.log("processing iteration", counter); // just here as // a sanity check to make sure

我在
async
函数中使用
for
循环,循环中包含
wait
。从我读到的内容来看,for循环应该可以很好地处理
await
,但似乎有一些不寻常的行为我不理解

考虑所描述的func,将其简化为场景的基本要素:

let counter = 0;
module.exports = async () => {
  console.log("processing iteration", counter); // just here as 
    // a sanity check to make sure multiple funcs aren't running 
    // concurrently to produce the out-of-order for loop iteration
  counter++;
  let keys = [... some array here ...]
  for (let i = 0; i < keys.length; i++) {
    let key = keys[i];
    console.log("processing iteration: [", counter, "] index: [", i, "]")
    if (keys[key] === false) {
      break;
    } else {
      if (Array.isArray(keys[key])) {
        let x = await doStuff(parseInt(key));
        // as suggested in an answer, I tried assigning the result 
        // to a variable to create a closure, but nothing changes 
        // in the output
        doOtherStuff(parseInt(key));
        delete keys[key];
      }
    }
  }
}
但是如果我确实使用了
await
,它需要用于按顺序完成这些异步任务(
doStuff
任务涉及数据库读取,因此我无法使它们同步),那么疯狂就会发生

具体来说,一旦使用了
await
,首先调用函数时,它的工作原理与预期基本相同:

processing iteration 15
processing iteration: [ 16 ] index: [ 0 ]
processing iteration: [ 16 ] index: [ 1 ]
processing iteration: [ 16 ] index: [ 2 ]
processing iteration: [ 16 ] index: [ 3 ]
processing iteration: [ 16 ] index: [ 4 ]
processing iteration: [ 16 ] index: [ 5 ]
processing iteration: [ 16 ] index: [ 6 ]
processing iteration: [ 16 ] index: [ 7 ]
processing iteration: [ 16 ] index: [ 8 ]
processing iteration: [ 16 ] index: [ 9 ]
processing iteration: [ 16 ] index: [ 10 ]
processing iteration: [ 16 ] index: [ 11 ]
processing iteration: [ 16 ] index: [ 12 ]
processing iteration: [ 16 ] index: [ 13 ]
但是随着模拟的进行,这个函数会被调用很多次,而那些日志显示它在第16次迭代时运行良好,只要内部发生了变化
doStuff
(更难解释内部到底发生了什么变化,但一旦满足某些条件,内部就会开始进行其他处理和循环)迭代器开始执行多次:

processing iteration 147
processing iteration: [ 148 ] index: [ 0 ]
processing iteration: [ 148 ] index: [ 1 ]
... something changes here with what's happening inside of doStuff ..
processing iteration: [ 148 ] index: [ 1 ]
processing iteration: [ 148 ] index: [ 1 ]
processing iteration: [ 148 ] index: [ 1 ]
processing iteration: [ 148 ] index: [ 1 ]
processing iteration: [ 148 ] index: [ 1 ]
processing iteration 148
processing iteration: [ 149 ] index: [ 0 ]
然后不仅索引重复,而且在以下func迭代计数中,循环的
开始按循环顺序进行迭代:

processing iteration 148
processing iteration: [ 149 ] index: [ 0 ]
processing iteration 149
processing iteration: [ 150 ] index: [ 0 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 1 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration 150
processing iteration: [ 151 ] index: [ 0 ]
processing iteration 151
processing iteration: [ 152 ] index: [ 0 ]
processing iteration: [ 152 ] index: [ 2 ]
processing iteration 152
processing iteration: [ 153 ] index: [ 0 ]
对于循环
for
async
await
是否有一些我根本无法理解的东西,只要看一下这段代码的简略版本就可以解释?一定有一些我遗漏了,因为在我看来,使用await时,对于那些
f或
循环迭代器以按顺序打印


如果需要,我将发布完整版本的代码,包括在
doStuff
中发生的事情,我只是对其进行了删节,以尽可能简洁地回答问题,除非需要更多的细节。

注意9000个日志,以及发生这种情况时索引的分解。外部函数是异步的,因此它们被放在事件循环中nd将与事件循环中的等待调用混合。
因此,等待之后的下一次迭代将在计数器的值已经递增后使用计数器的值。
还请注意,输出在经过1秒之后发生

关键之处在于等待类似于一个“”,它使它退出函数并产生一个承诺,并将其放入事件循环中

因此,可能发生的情况是,当一个等待被命中时,执行被延迟,因此计数器在等待位置等待事件循环时被更改

for(让i=0;inew Promise(r=>Math.random(){}
var计数器2=0
设计数器=0;
module.exports=async()=>{
log(“正在处理迭代”,计数器);//如下所示
//一个健全的检查,以确保多个函数没有运行
//同时为循环迭代生成无序
计数器++;
控制台日志(计数器2)
设keys=[1,2,6,6,1,6[1],[1],10]
for(设i=0;i
如果这里没有一些基本的、立即明显的行为解释,请告诉我,我会发布未删节的代码,包括在
doStuff
wow中发生的事情,这真的很棘手。通过将for循环转换为递归函数调用,在con之前等待每个承诺完成,可以解决这个问题吗tinuing?这实际上构成了“按预期工作”,因为async/await应该延迟执行,并且“已修复”必须取决于您尝试执行的操作。当导出的函数是异步的且调用代码没有等待时,您不应该依靠全局变量
计数器来跟踪执行流顺序。基本上,您唯一应该“依赖”的是“承诺”对于变量
计数器
,如果等待对变量
计数器
起作用的所有调用,则它将达到
10
(或它应该得到的任何结果)。全局问题请参见第二个示例,在这两个示例之间执行不会延迟,因为对module.exports()的每个调用在继续下一个调用之前等待。其要点是一路异步到“顶部”。如果我有多个对Promise wrapped或async函数的调用,如果我没有显式地等待它们,我应该预期它们可能会被延迟,并且它们的Promise解析的顺序可能会有所不同。请注意,第二个示例是如何在1秒内成批解析的,而不是像第一个示例那样立即完成并执行所有这些函数在等待后1秒钟后,值为9000。感谢您的时间和帮助。这解决了我的问题
processing iteration 148
processing iteration: [ 149 ] index: [ 0 ]
processing iteration 149
processing iteration: [ 150 ] index: [ 0 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration: [ 150 ] index: [ 1 ]
processing iteration: [ 150 ] index: [ 2 ]
processing iteration 150
processing iteration: [ 151 ] index: [ 0 ]
processing iteration 151
processing iteration: [ 152 ] index: [ 0 ]
processing iteration: [ 152 ] index: [ 2 ]
processing iteration 152
processing iteration: [ 153 ] index: [ 0 ]