脚本宝典收集整理的这篇文章主要介绍了JS异步堆栈追踪之为什么await胜过Promise,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
async/await和Promise的根本区别在于awaIT fn()暂停当前函数的执行,而PRomise.then(fn)在将fn调用添加到回调链后,继续执行当前函数。
const fn = () => console.LOG('hello') const a = async () => { await fn() // 暂停 fn 的执行 } // 调用 a 时,才恢复 fn 的执行 a() // "hello" const promise = Promise.resolve() // 将 fn 添加到回调链后,继续执行 fn promise.then(fn) // "hello"
在堆栈追踪的上下文中,这种差异非常显著。
当一个Promise链(无论是否脱糖化)在任何时候抛出一个未经处理的异常时,JavaScript引擎都会显示一条错误信息和(希望)记录一个有用的堆栈追踪。
作为一名开发人员,无论您使用的是普通的Promise还是async await,您都会期望这样。
想象一个场景,当对异步函数b的调用解析时,调用函数c:
const b = () => Promise.resolve() const a = () => { b().then(() => c()) }
当调用a时,将同步发生以下情况:
之后,我们完成了在函数a的主体中执行代码。a永远不会被挂起,当对b的异步调用解析时,上下文已经消失了。
想象一下如果b(或c)异步抛出异常会发生什么?理想情况下,堆栈追踪应该包括a,因为b(或c)是从那里调用的,对吧?既然我们不在参考a了 ,那怎样能做到呢?
为了让它工作,JavaScript 引擎需要在上面的步骤之外做一些事情:它在有机会的时候捕获并存储堆栈追踪。
在V8中,堆栈追踪附加到b返回的Promise。当Promise实现时,堆栈追踪将被传递,以便c可以根据需要使用它。
b()[a] -> b().then()[a] -> c[a?:a]
捕获堆栈追踪需要时间(即降低性能);存储这些堆栈追踪需要内存。
下面是同样的程序,使用async/await而不是Promise编写:
const b = () => Promise.resolve() const a = async () => { await b() c() }
使用await,即使在await调用中不收集堆栈追踪,我们也可以恢复调用链。
这是可能的,因为a被挂起,正在等待b解决。如果b抛出异常,则可以按需以这种方式重建堆栈追踪。
如果c抛出异常,堆栈追踪可以像同步函数那样构造,因为发生这种情况时,我们仍在a上下文中。
通过遵循以下建议,使 JavaScript 引擎能够以更高效的方式处理堆栈追踪:
以上就是JS异步堆栈追踪之为什么await胜过Promise的详细内容,更多关于Javascript的资料请关注脚本宝典其它相关文章!
以上是脚本宝典为你收集整理的JS异步堆栈追踪之为什么await胜过Promise全部内容,希望文章能够帮你解决JS异步堆栈追踪之为什么await胜过Promise所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。