Javascript承诺会阻止堆栈吗

Javascript承诺会阻止堆栈吗,javascript,promise,async-await,dom-events,event-loop,Javascript,Promise,Async Await,Dom Events,Event Loop,使用Javascript承诺时,事件循环是否被阻止 我的理解是,使用await&async会使堆栈停止,直到操作完成。它是通过阻塞堆栈来实现这一点,还是类似于回调并将进程传递给各种API?一个wait只阻塞当前的异步函数,事件循环继续正常运行。当承诺解决时,函数体的执行将在其停止的位置恢复 每个async/wait都可以在一个等价的中进行转换。然后(…)-回调程序,从并发性的角度来看,它的工作方式就是这样。因此,当承诺正在等待时,其他事件可能会触发,其他任意代码可能会运行 使用Javascrip

使用Javascript承诺时,事件循环是否被阻止


我的理解是,使用await&async会使堆栈停止,直到操作完成。它是通过阻塞堆栈来实现这一点,还是类似于回调并将进程传递给各种API?

一个
wait
只阻塞当前的
异步函数,事件循环继续正常运行。当承诺解决时,函数体的执行将在其停止的位置恢复

每个
async
/
wait
都可以在一个等价的
中进行转换。然后(…)
-回调程序,从并发性的角度来看,它的工作方式就是这样。因此,当承诺正在等待时,其他事件可能会触发,其他任意代码可能会运行

使用Javascript承诺时,事件循环是否被阻止

不是。承诺只是一个事件通知系统。它们本身不是一种手术。他们只需调用相应的
.then()
catch()
处理程序来响应被解析或拒绝,如果链接到其他承诺,他们可以延迟调用这些处理程序,直到链接到它们的承诺也被解析/拒绝。因此,单个承诺不会阻止任何事情,当然也不会阻止事件循环

我的理解是,使用await&async会使堆栈停止 直到操作完成。它是通过阻止 堆栈还是它的行为类似于回调并将进程传递给 某种API

await
是一种简单的语法糖,它用更简单的语法替换了
.then()
处理程序。但是,在封面下,操作是相同的。在
wait
之后出现的代码基本上被放在一个不可见的
.then()
处理程序中,事件循环没有阻塞,就像
.then()
处理程序没有阻塞一样


请注意以下评论之一:

现在,如果您要构造代码,用不断解析的承诺(在这里的一些注释中提出的某种无限循环中)覆盖事件循环,然后,事件循环将一次又一次地处理来自微任务队列的不断解析的承诺,并且永远不会有机会处理等待在事件循环中的宏任务(其他类型的事件)。事件循环仍在运行,并且仍在处理微任务,但是如果您不断向其中填充新的微任务(已解决的承诺),那么它可能永远不会到达宏任务。关于是否将其称为“阻止事件循环”,似乎存在一些争论。这只是一个术语问题——更重要的是实际发生了什么。在这个无限循环反复不断解析新承诺的示例中,事件循环将继续处理这些解析的承诺,而事件队列中的其他事件将不会得到处理,因为它们永远不会到达队列的最前面来轮到它们。这通常被称为“饥饿”,而不是“阻塞”,但问题是,如果您持续不断地将新的微任务放入队列中,宏任务可能无法得到服务


在Javascript中应该避免这种无限循环不断解析新承诺的概念。它可能会使其他活动失去获得服务的机会。

如上所述的其他活动。。。承诺就像一个事件通知系统,
async/await
then()
相同。但是,要非常小心,可以通过执行阻塞操作来“阻塞”事件循环。请查看以下代码:

function blocking_operation_inside_promise(){
    return new Promise ( (res, rej) => {
        while( true ) console.log(' loop inside promise ')
        res();
    })
}

async function init(){
    let await_forever = await blocking_operation_inside_promise()
}

init()
console.log('END')
结束日志将永远不会打印。JS是单线程的,该线程现在很忙。你可以说整个事情都被阻塞操作“阻塞”了。在这种特殊情况下,事件循环本身不会被阻塞,但它不会向应用程序传递事件,因为主线程正忙

JS/Node是一种非常有用的编程语言,在使用非阻塞操作(如网络操作)时非常有效。但不要用它来执行非常密集的CPU算法。如果你在浏览器中考虑使用Web工作者,如果你在服务器端使用工作线程、子进程或微服务架构。 Javascript承诺会阻止堆栈吗

不,不是那堆。在承诺的回调开始执行之前,当前作业将一直运行到完成

使用Javascript承诺时,事件循环是否被阻止

是的。 不同的环境有不同的事件循环处理模型,所以我将要讨论的是,尽管nodejs的模型稍微简单一些,但它们实际上公开了相同的行为

在浏览器中,承诺的回调(PromiseReactionJob在ES术语中)实际上是以所谓的方式执行的。
微任务是一项特殊任务,在特殊的环境中。 该微任务队列在称为a的单个过程中被多次访问,例如在主任务完成之后、在执行诸如调整大小之类的渲染事件之后、在每个动画帧回调之后等等

这些微任务检查点是事件循环的一部分,与任何其他任务一样,它们会在运行时阻止事件循环。
然而,更重要的是,从微任务检查点调度的微任务将由同一个微任务检查点执行

这意味着使用承诺这一简单事实不会让您的代码让事件循环呼吸,就像
setTimeout()
调度任务可以做的那样,即使js堆栈已经清空,并且在调用回调之前已经完全执行了上一个任务,您仍然可以很好地完全锁定事件循环,决不允许它继续执行任何其他任务,甚至不允许更新渲染:

<代码