在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
概述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,您都会期望这样。 Promise想象一个场景,当对异步函数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下面是同样的程序,使用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的资料请关注极客世界其它相关文章! |
请发表评论