深入理解 await 与 async

深入理解 await 与 async
最新回答
安旭薇

2021-01-13 00:13:57

深入理解 await 与 async

一、基本概念

  1. async 函数

    async 函数是一个返回 Promise 对象的函数。

    在函数内部,你可以使用 await 关键字来等待一个 Promise 的结果。

  2. await 关键字

    await 关键字只能在 async 函数内部使用。

    它会暂停当前 async 函数的执行,直到等待的 Promise 完成,并返回 Promise 的结果。

二、错误处理

  • 使用 try/catch 结构

    在使用 await 时,如果遇到 Promise 被拒绝(即出错),可以使用 try/catch 结构来捕获错误。

    try/catch 在 async/await 中的作用与在同步代码中的作用类似,用于捕获异常并处理。

  • 处理多个 await 调用中的并发错误

    如果需要同时等待多个 Promise,并希望在其中一个 Promise 失败时立即处理错误,可以使用 Promise.all()。

    Promise.all() 会返回一个 Promise,该 Promise 在所有传入的 Promise 都成功完成时才会完成;如果其中一个 Promise 被拒绝,则立即被拒绝,并可以通过 try/catch 捕获错误。

三、并发性

  • 并发执行多个 await 操作

    使用 Promise.all() 可以并发执行多个 Promise,并在所有 Promise 都完成时返回结果。

    Promise.allSettled() 也是用于并发执行多个 Promise 的方法,但它会在所有 Promise 都完成(无论是成功还是失败)时返回结果。

  • Promise.all() 和 Promise.race() 的作用

    Promise.all() 允许你并发等待多个 Promise,并返回一个在所有 Promise 都完成时完成的 Promise。

    Promise.race() 返回一个 Promise,该 Promise 在第一个传入的 Promise 完成(无论是成功还是失败)时就会完成。

四、与 Promise 的关系

  • async/await 是基于 Promise 的

    async/await 提供了一种更简洁、更直观的方式来处理 Promise。

    在 async 函数中返回一个值,等价于调用 Promise.resolve()。

    在 async 函数中抛出错误,等价于调用 Promise.reject()。

五、执行顺序

  • 包含多个 await 语句的 async 函数的执行顺序

    函数会从顶部开始执行,当遇到第一个 await 语句时暂停,直到该 Promise 完成。

    然后,函数会继续执行,直到遇到下一个 await 或函数结束。

  • 何时使用 await 和何时避免使用

    当你需要按顺序执行异步操作时,使用 await。

    当你可以并发执行多个操作时,使用 Promise.all() 或其他类似的方法,以避免不必要的等待。

六、错误和陷阱

  • 常见错误或陷阱

    忘记使用 await,导致异步操作没有按预期等待。

    在非 async 函数内部使用 await,导致语法错误。

    在循环中不正确地使用 await,导致不必要的顺序执行,影响性能。

    未处理的异步错误,可能导致程序崩溃或不稳定。

  • 避免“忘记 await”的问题

    使用 TypeScript 或 ESLint 这样的工具,它们可以检测并提示你忘记使用 await 的情况。

七、实际应用

  • 将给定代码片段转换为使用 async/await 或 Promises

    这需要根据具体的代码片段来决定,通常是将基于 Promise 的回调地狱转换为更简洁的 async/await 代码。

八、浏览器和 Node.js 支持

  • 支持情况

    Node.js 从 7.6.0 版本开始支持 async/await。

    大多数现代浏览器都支持 async/await,但旧版本的浏览器可能不支持。

  • 在不支持的环境中使用

    可以使用 Babel 或 TypeScript 这样的转译器,将 async/await 代码转换为 ES5 或 ES6 JavaScript,以在不支持的环境中运行。

九、性能和最佳实践

  • 性能差异

    在大多数情况下,async/await 与纯 Promises 的性能差异是可以忽略的。

    但 async/await 可能会带来一些额外的运行时开销,特别是在大量异步操作的情况下。

  • 何时使用

    当你需要更简洁和可读的代码时,使用 async/await。

    对于复杂的异步逻辑或需要更细粒度控制的场景,使用 Promises。

十、其他特性和提议

  • async iterators 和 for-await-of

    async iterators 是一种可以异步生成值的迭代器。

    for-await-of 是一种循环结构,允许你等待 async iterator 的每个值,从而简化异步迭代操作。

  • 顶级 await

    顶级 await 是一个提议,允许你在模块的顶级使用 await,而不是仅在 async 函数中。

    这可以简化模块间的异步依赖管理。