javascript中的同步和异步循环

neo*_*Dev 19 javascript

JavaScript中的循环是同步还是异步?(for,while等)

假设我有:

for(let i=0; i<10; i++){
    // A (nested stuff...)
}

// B ...
Run Code Online (Sandbox Code Playgroud)

使用for执行B会在A有时开始...(所以异步)

有没有办法以同步方式使用语句?

jam*_*non 18

当所有异步操作都启动时,for循环立即运行完成.

好吧,这里有一些嵌套循环.请注意,"BBB"总是在之后发射.

for(let i=0; i<10; i++){
   for(let i=0; i<10; i++){
     for(let i=0; i<10; i++){
       console.log("AA")
     }
   }
}

console.log('BBB')
Run Code Online (Sandbox Code Playgroud)

现在,看看这个

for(let i=0; i<10; i++){
   setTimeout(function() {console.log("AA")}, 2000)
}

console.log('BBB')
Run Code Online (Sandbox Code Playgroud)

这是因为所谓的"事件循环".事实上,使用setTimeout我们正在模拟异步操作.它可能是ajax调用或其他异步进程.

看看这个:http://latentflip.com/loupe

这将真正帮助您了解这些异步/同步循环主题.

更新以显示承诺如何在这里工作(给出以下评论):

var stringValues = ['yeah', 'noooo', 'rush', 'RP'];
var P = function(val, idx){
    return new Promise(resolve => setTimeout(() => resolve(val), 1000 * idx));
};


// We now have an array of promises waiting to be resolved.
// The Promise.all basically will resolve once ALL promises are 
// resolved. Keep in mind, that if at any time something rejects
// it stops

// we iterator over our stringValues array mapping over the P function, 
// passing in the value of our array.
var results = Promise.all(stringValues.map(P));

// once all are resolved, the ".then" now fires. It is here we would do 
results.then(data => 
    console.log(data) //["yeah", "noooo", "rush", "RP"]
);
Run Code Online (Sandbox Code Playgroud)

如果我不够清楚,请告诉我.

  • darnit这不是“同步”类型的循环-所有超时都在同一时间触发;只是等待被1000 * idx错开了 (2认同)

Fer*_*jal 8

如果您将异步循环放在a内,for...loop并希望停止循环直到每个操作结束,则必须使用如下async/await语法。

async function foo() {
    var array = [/* some data that will be used async*/]

    //This loop will wait for each next() to pass the next iteration
    for (var i = 0; i < array.length; i++) { 
        await new Promise(next=> {
            someAsyncTask(array[i], function(err, data){
                /*.... code here and when you finish...*/
                next()
            })
        })        
    }
}

foo().then(() => { /*After foo execution*/ })
Run Code Online (Sandbox Code Playgroud)

  • @tiomno是的,那是因为 foo 是一个 Promise,只需将该代码放入 `foo().then(() =&gt; { /*此处为您的代码*/ })` (2认同)

Lao*_*tih 6

首先,你关于用于 B 的执行有时会在 A 之前开始......(所以异步)的说法是错误的。

Javascript中的循环函数(如whilefor或)将同步运行(阻塞.forEach) ,无论您是在浏览器中运行还是在NodeJS运行时环境中运行。我们可以通过运行下面的代码来证明这一点(也许这个过程需要几秒钟):.map

let counter1 = 0
let counter2 = 0
let counter3 = 0

console.log("Start iteration")
console.time("Time required")

// First heavy iteration
for (let i = 0; i < 1000; i++) {
  counter1 += 1

  // Second heavy iteration
  for (let i2 = 0; i2 < 1000; i2++) {
    counter2 += 1

    // Third heavy iteration
    for (let i3 = 0; i3 < 1000; i3++) {
      counter3 += 1
    }
  }
}

console.log("Iteration was successful")
console.timeEnd("Time required")
console.log('The value of `counter1` is: ' + counter1)
console.log('The value of `counter2` is: ' + counter2)
console.log('The value of `counter3` is: ' + counter3)
Run Code Online (Sandbox Code Playgroud)

那么什么样的循环会导致您的代码异步运行(非阻塞)?

答案是:

放置在Promise 回调functionwith关键字或一些带有回调(并非全部)async的本机函数(如、等)内的代码将异步运行。setTimeoutsetInterval

例子:

setTimeout(() => {
  console.log('A')
})

console.log('B')
Run Code Online (Sandbox Code Playgroud)

在代码中,setTimeout首先声明函数。但是,代码的输出显示该console.log('B')函数的运行时间早于该setTimeout函数。


jal*_*oso 5

let items = YourArray;
let i = 0;
await new Promise(async (resolve, reject) => {
    try {
        if (items.length == 0) return resolve();
        let funSync = async () => {
            await yourASyncFunctions(items[i].doAnything);
            i++;
            if (i == items.length) resolve();
            else funSync();
        }
        funSync();
    } catch (e) {
        reject(e);
    }
});
Run Code Online (Sandbox Code Playgroud)