Javascript 延迟承诺。全部赢得';调用睡眠功能后,如果增加睡眠时间,则无法工作
在JS中编写代码时,我发现了有趣的行为 如以下代码所示,从Javascript 延迟承诺。全部赢得';调用睡眠功能后,如果增加睡眠时间,则无法工作,javascript,typescript,Javascript,Typescript,在JS中编写代码时,我发现了有趣的行为 如以下代码所示,从sleep(0)开始不会产生任何延迟,而sleep(15)会产生延迟 //sleep.ts 导出默认函数睡眠(t:编号):承诺{ 返回新承诺((resolve)=>setTimeout(resolve,t)); } //loop.ts 异步函数doLoop(){ 设延迟=0; 常数增量=15; 等待承诺( 新数组(10).fill(0).map(异步()=>{ //这不行,不能耽搁。 等待睡眠(延迟); 延迟+=增量; //这很有效。
sleep(0)
开始不会产生任何延迟,而sleep(15)
会产生延迟
//sleep.ts
导出默认函数睡眠(t:编号):承诺{
返回新承诺((resolve)=>setTimeout(resolve,t));
}
//loop.ts
异步函数doLoop(){
设延迟=0;
常数增量=15;
等待承诺(
新数组(10).fill(0).map(异步()=>{
//这不行,不能耽搁。
等待睡眠(延迟);
延迟+=增量;
//这很有效。
延迟+=增量;
等待睡眠(延迟);
}
)
)
}
这两者有什么区别
在下面试试
//sleep.ts
功能睡眠(t){
返回新承诺((resolve)=>setTimeout(resolve,t));
}
//loop.ts
异步函数doLoop(){
设延迟=0;
常数增量=1000;
等待承诺(
新数组(3).fill(0).map(异步()=>{
//这不行,不能耽搁。
等待睡眠(延迟);
控制台日志(1,延迟);
延迟+=增量;
//这很有效。
延迟+=增量;
等待睡眠(延迟);
控制台日志(2,延迟);
}
)
)
}
doLoop()代码>TLDR:
map()
回调函数使用当前值delay
和increment
,为数组中的每个项创建一个新的执行范围/上下文,然后将其推入回调队列,等待执行
在执行期间,每个回调的第一个等待睡眠(延迟)
以0毫秒的延迟执行
让我们想想JavaScript中的事件循环和闭包
调用堆栈
调用堆栈是事件循环过程的一部分,它基本上保持
当前正在运行的函数的状态。这和我的想法很相似
堆栈数据结构的概念。(后进先出-后进先出)
现在,当调用doLoop()
函数时,它被添加到调用堆栈中,并且在执行期间,它初始化变量delay
和increment
,并分别赋值0
和1000
接下来,它运行await Promise.all()
,它也被添加到调用堆栈中以开始执行
接下来,new Array(3).fill(0)
被添加到调用堆栈中并执行,然后返回[0,0,0]
,该返回值被链接到Array.map()
,该值也被添加到调用堆栈中以开始执行
Array.map()
对循环中的每个项执行的操作,并返回一个新数组
回调队列
这是事件循环过程的另一部分,异步代码被推送到事件循环过程中,并等待
执行。函数在这里排成一个队列,调用堆栈在这里查看,以获取完成后要执行的内容
链式.map()
函数接受一个回调函数,该函数被相应地推送到回调队列中,因为它们是异步函数
闭包
这是函数记住创建它的范围/上下文的时候
即使函数在不同的范围内执行
将每个回调推入回调队列时,将根据当前值delay
和increment
创建一个新的执行范围/上下文
第一个wait sleep(delay)
以delay
值0
执行,因为这是将其推入调用堆栈时的delay
值
当第二个等待睡眠(延迟)
在延迟增加后在调用堆栈中执行时,因此造成了实际的等待。你怎么知道第一次睡眠没有延迟?我用console.time
和console.timeEnd
找到了答案。但是当它运行时,你的初始延迟只有0毫秒,这不解释为什么没有延迟吗?对不起,我没有正确阅读你的评论。我以为你说的是整个循环。可能第一个循环没有延迟,但是我指的是整个循环。谢谢你的详细解释!因此,根据我的理解,在第一种情况下,所有sleep
函数都被推回到回调队列中,然后所有增量都发生在每个sleep
函数完成之后。我理解正确了吗?*所有增量->每个增量是的,这是正确的。