关于await阻塞问题

async / await最大的优点就是已同步代码的方式,执行异步操作。
在async修饰的异步函数中,await修饰的请求方法

async fn(){
let res1 = await fn1() 
let res2 = await fn2() 
let res3 = await fn3() 
}

保证回调完成的顺序。

async / await不会阻止整个主线程. node.js仍然将所有Javascript作为单线程运行,即使某些代码在async / await上等待,其他事件仍然可以运行其事件处理程序(因此node.js不会被阻止).事件队列仍在为其他事件提供服务.实际上,它将是一个事件,它解决了一个允许等待停止等待并运行以下代码的承诺.

像这样的代码:

await foo(); // foo is an async function that returns a promise
console.log(“hello”);
类似于:

foo().then(() => {
console.log(“hello”);
});
因此,等待只是将该范围中的以下代码放入一个不可见的.then()处理程序中,其他所有内容的工作方式与使用.then()处理程序实际编写的内容完全相同.

因此,await允许您保存.then()处理程序的写入并为代码提供同步外观(尽管它不是真正的同步).最后,它是一种速记,可让您使用较少的代码行编写异步代码.人们确实需要记住,任何可以拒绝的承诺必须在它周围的某个地方有一个try / catch来捕获和处理拒绝.

从逻辑上讲,您可以考虑在执行函数时遇到await关键字时node.js执行的操作如下:

1.进行函数调用
2.解释器看到该函数被声明为异步,这意味着它将始终返回一个promise.
3.解释器开始执行该功能.
4.当遇到await关键字时,它会暂停该函数的进一步执行,直到正在等待的promise被解决.
5.然后该函数返回一个未解决的promise.
6.此时,解释器继续执行函数调用之后的任何内容(通常是fn().then()后面跟着其他代码行). .then()处理程序尚未执行,因为尚未解析承诺.
7.在某些时候,这个Javascript序列完成并将控制权返回给解释器.
8.解释器现在可以自由地从事件队列中提供其他事件.进入await关键字的原始函数调用仍处于暂停状态,但现在可以处理其他事件.
93在未来的某个时刻,正在等待的原始承诺得到解决.当在事件队列中处理该事件时,先前挂起的函数在等待之后继续在该行上执行.如果还有await语句,那么函数执行将再次暂停,直到该promise得到解决.
10.最终函数命中一个return语句或到达函数体的末尾.如果存在返回xxx语句,则评估xxx,其结果将成为此异步函数已返回的promise的已解析值.该函数现在已完成执行,并且之前返回的承诺已得到解决.
11.这将导致任何附加到此函数先前返回的promise的.then()处理程序被调用.
12.在那些.then()处理程序运行之后,最终完成了这个异步函数的工作.

因此,虽然整个解释器没有阻塞(其他Javascript事件仍然可以被服务),但是包含await语句的特定异步函数的执行被暂停,直到等待的promise被解决.
重要的是要理解上面的步骤5.当第一个await被命中时,该函数在执行此函数之后立即返回未解析的promise和代码(在等待的promise被解析之前).出于这个原因,整个翻译都没有被阻止.执行继续.只有一个函数的内部才会被暂停,直到承诺得到解决.

总结:
await的阻塞方式并不是阻塞同步代码所在的主线程,await其实是阻塞的当前异步函数的异步线程。
虽然await会阻塞async异步函数,但是并没有阻塞同步代码的主线程,同步和异步之间仍然相互不阻塞。
虽然await阻塞异步函数向后执行,看起来像是同步的,但是它本质还是异步的,我们同样可以并行执行其他的不关联的异步操作,而同步函数不能并行执行。

你可能感兴趣的:(javascript)