迹忆客 专注技术分享

当前位置:主页 > 学无止境 >

异步堆栈跟踪:为什么 await 击败了 Promise#then()

作者:迹忆客 最近更新:2023/01/09 浏览次数:

与直接使用 promises 相比,asyncawait 不仅可以使开发人员的代码更具可读性——它们还可以在 JavaScript 引擎中实现一些有趣的优化! 这篇文章是关于这样一种优化,涉及异步代码的堆栈跟踪。

awaitvanilla promises 的根本区别在于 await X() 暂停当前函数的执行,而 promise.then(X) 在将 X 调用添加到回调链后继续执行当前函数。 在堆栈跟踪的上下文中,这种差异非常显着。

promise 链在任何时候抛出未处理的异常时,JavaScript 引擎会显示错误消息和(希望如此)有用的堆栈跟踪。 作为一名开发人员,无论我们使用普通的 promise 还是 asyncawait,我们都期望这一点。关于 promise 也可以参考我们之前的如何创建自己的 Promise这篇文章。

Vanilla promise

想象一个场景,当对异步函数 b 的调用解析时调用函数 c

const a = () => {
    b().then(() => c());
};

调用 a 时,会同步发生以下情况:

  • b 被调用并返回一个 promise ,该 promise 将在未来某个时候解决。
  • .then 回调(实际上是调用 c())被添加到回调链中(或者,用 V8 术语来说:[...] 被添加为解析处理程序)。

之后,我们就完成了函数 a 中的代码的执行。 a 永远不会挂起,并且在对 b 的异步调用解决时上下文已经消失。 想象一下如果 b(或 c)异步抛出异常会发生什么。 堆栈跟踪应该包括 a,因为那是调用 b(或 c)的地方,对吗? 既然我们不再提及 a ,那怎么可能呢?

为了让它工作,JavaScript 引擎需要在上述步骤之外做一些事情:它在它仍有机会的时间内捕获并存储堆栈跟踪。 在 V8 中,堆栈跟踪附加到 b 返回的 promise 。 当 promise 执行时,堆栈跟踪将被传递,以便 c 可以根据需要使用它。

捕获堆栈跟踪需要时间(即降低性能); 存储这些堆栈跟踪需要内存。

async/await

这是同一个程序,使用 async/await 而不是 vanilla promises 编写:

const a = async () => {
    await b();
    c();
};

使用 await,即使我们没有在 await 调用时收集堆栈跟踪,我们也可以恢复调用链。 这是可能的,因为 a 被挂起,等待 b 解析。 如果 b 抛出异常,则可以通过这种方式按需重建堆栈跟踪。 如果 c 抛出异常,则可以像同步函数一样构建堆栈跟踪,因为我们仍在发生这种情况的时候。

建议

与大多数看似“只是语法糖”的 ECMAScript 功能一样,async/await 不止于此。

遵循以下建议,使 JavaScript 引擎能够以更高效和内存效率更高的方式处理堆栈跟踪:

  • vanilla promises 更喜欢 async/await
  • 使用 @babel/preset-env 避免不必要地转译 async/await

尽管 V8 尚未实现此优化,但遵循此建议可确保我们(或其他 JavaScript 引擎)实现后的最佳性能。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 TypeScript 中返回一个 Promise

发布时间:2023/03/19 浏览次数:182 分类:TypeScript

本教程讨论如何在 TypeScript 中返回正确的 Promise。这将提供 TypeScript 中 Returns Promise 的完整编码示例,并完整演示每个步骤。

深度理解 ES6 Promise

发布时间:2023/03/07 浏览次数:138 分类:WEB前端

现在我们开始 ES6 深度系列。 如果大家以前从未来到过这里,请从 ES6 教程 开始。 这篇是关于 ES6 中的 Promise API。 如果觉得该动画非常复杂,请继续阅读! Promises 是一个非常复杂的范

JavaScript 中检查函数是否返回的 Promise

发布时间:2022/12/15 浏览次数:556 分类:JavaScript

要检查函数是否返回 Promise ,请检查函数是否异步或调用它并检查函数是否返回具有函数类型 then 属性的对象。 如果满足任一条件,该函数将返回一个 Promise 。 // ✅ Promise check functio

JavaScript 中 Promise.resolve is not a constructor 错误

发布时间:2022/12/02 浏览次数:212 分类:JavaScript

当我们尝试将 Promise.resolve() 方法与 new 运算符一起使用时,会出现Promise.resolve is not a constructor错误。 Promise.resolve() 方法不是构造函数,因此应该在没有 new 运算符的情况下使用它,例如

JavaScript 中如何访问 Promise 的值

发布时间:2022/12/02 浏览次数:75 分类:JavaScript

使用 Promise.then() 方法访问承诺的值,例如 p.then(value = console.log(value)) 。 then() 方法接受一个函数,该函数将 promise 的解析值作为参数传递。 // ?️ Example promise const p = Promise . resolve (

JavaScript 中检查函数是否返回 Promise

发布时间:2022/12/02 浏览次数:70 分类:JavaScript

要检查函数是否返回 Promise ,请检查函数是否异步或调用它并检查函数是否返回具有函数类型 then 属性的对象。 如果满足任一条件,该函数将返回一个 Promise 。 // ✅ Promise check functio

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便