Javascript 在for循环中等待setTimeout可以吗?
在Javascript 在for循环中等待setTimeout可以吗?,javascript,node.js,for-loop,async-await,settimeout,Javascript,Node.js,For Loop,Async Await,Settimeout,在Async/Await之前,当我们需要每隔X秒进行一次循环N时,我们可以选择使用for循环来包装settimeout,或者在setinterval周围使用包装器来计算执行并清除它的次数 但是使用async await可以这样做: async function newFashion() { for (let i = 0; i < 10; i++) { console.log(i); await sleep(1000); } console.log("Finish
Async/Await
之前,当我们需要每隔X秒进行一次循环N时,我们可以选择使用for循环来包装settimeout
,或者在setinterval
周围使用包装器来计算执行并清除它的次数
但是使用async await可以这样做:
async function newFashion() {
for (let i = 0; i < 10; i++) {
console.log(i);
await sleep(1000);
}
console.log("Finish");
}
newFashion(); // 0 1 2 3 4 5 6 7 8 9 Finish
function oldFashion() {
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, i * 1000);
}
console.log("Finish");
}
oldFashion(); // Finish 0 1 2 3 4 5 6 7 8 9
function sleep(time) {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
}
异步函数newFashion(){
for(设i=0;i<10;i++){
控制台日志(i);
等待睡眠(1000);
}
控制台日志(“完成”);
}
newFashion();//01 2 3 4 5 6 7 8 9完成
函数oldFashion(){
for(设i=0;i<10;i++){
设置超时(()=>{
控制台日志(i);
},i*1000);
}
控制台日志(“完成”);
}
oldFashion();//完成0 1 2 3 4 5 6 7 8 9
功能睡眠(时间){
返回新承诺((解析)=>{
setTimeout(解析,时间);
});
}
我知道这两个人的行为不一样oldFashion()
实际上并不在循环中“暂停”,而是在迭代时实际调用10setTimeout()
,因此基本上他用10setTimeout()
填充事件循环
newFashion()
不管它的行为如何,当他点击wait时,他会“停止”迭代,但我不确定它到底是如何工作的
那么,用NsetTimeout()
填充事件循环,或者一个接一个地等待,还有什么更好呢?在newFashion()中实际发生了什么
编辑:更具体地说,每种方法在性能方面的收益是什么?当N很小时?当N很大时
在newFashion()中实际发生了什么
wait
表达式导致对newFashion
函数的调用暂停,直到sleep
函数的结果(承诺)被解决或拒绝。解析或拒绝后,它将继续代码的其余部分
那么,用N setTimeout()填充事件循环,或者
一个接一个地等待
如您所见,async/await
部分更具可读性。如果环境支持ES8
,您可以自由使用它async/await
也是熟悉的程序员之一,他们是从C#等语言进入Javascript的,C#也使用async/await
进行异步编程。对于他们来说,使用async/await
比使用for loop
示例更方便。这里有一个编写“老式”版本的更好方法。它保留了让“Finish”
日志排在最后的期望行为,并且不依赖于在将来的不同时间间隔立即设置一系列计时器
整个事情都是自足和清晰的
函数betterOldFashion(i,n){
if(i betterOldFashion(0,10)代码>我不相信你的新代码有任何问题,我个人觉得它更容易阅读。我个人更喜欢constdelay=time=>newpromise(res=>setTimeout(res,time))代码>;)@科迪格。哈哈,我们这里要简单一点;)旧方法的可读性较差,部分原因是新方法将一部分工作转移到单独的功能中。而且,旧方法不会非常准确。首先,我不会使用for
循环,如果您更感兴趣,它实际上不会在拒绝承诺后继续执行代码<代码>等待
如果其操作数承诺被拒绝,则抛出拒绝的原因。然后,抛出将拒绝调用async
函数返回的承诺,除非它在try/catch块中被捕获。@traktor53您是对的。但无论如何,控件都会返回到async
函数。它可以处理错误或通过调用堆栈抛出错误。第二个代码段真的很可怕。太脆弱了…@Bergi:它基本上和OP的代码一样,正如我所说,这是不可取的。我只是重新设计了这个解决方案,以显示通过将代码移出函数而获得的可读性差异,这就是OP对异步/等待版本所做的。