小工具知识网

当前位置: 首页 > 行业知识 > 【JavaScript】async function和await的介绍和使用

行业知识

【JavaScript】async function和await的介绍和使用

2026-10-26 20:37:34 来源:互联网转载

简言

async/await是现在常用的一套处理异步函数的方式,更确切的是它们是用来处理Promise的方式。

async/await 的目的在于简化使用基于 promise 的 API 时所需的语法。

异步函数(async function)

async function 声明创建一个绑定到给定名称的异步函数。函数体内允许使用 await 关键字,这使得我们可以更简洁地编写基于 promise 的异步代码,并且避免了显式地配置 promise 链的需要。

上面sync指的就是异步函数。

有两种方式可以创建异步函数:

  • async function 函数声明 — 创建声明一个异步函数
  • async function 关键字表达式 — 创建一个异步匿名函数并赋给一个变量(也可以使用IIFE,立即执行函数)。
    async function foo() {  return 1;}const one = async function(){}(async function(){})()

    异步函数和普通函数区别:

    • 异步函数可以处理promise。
    • 每次调用异步函数时,都会返回一个新的 Promise 对象,该对象将会被解决为异步函数的返回值,或者被拒绝为异步函数中未捕获的异常。
    • 异步函数可以包含零个或者多个 await 表达式。await 表达式通过暂停执行使返回 promise 的函数表现得像同步函数一样,直到返回的 promise 被兑现或拒绝。返回的 promise 的解决值会被当作该 await 表达式的返回值使用 async/await 关键字就可以使用普通的 try/catch 代码块捕获异步代码中的错误。
      async function foo() {  await 1;}

      相当于:

      function foo() {  return Promise.resolve(1).then(() => undefined);}

      await

      await 操作符用于等待一个 Promise 兑现并获取它兑现之后的值。它只能在异步函数或者模块顶层中使用。

      await expression;

      expression为要等待的 Promise 实例,Thenable 对象,或任意类型的值。

      当一个 Promise 被传递给 await 操作符,await 将等待该 Promise 兑现,并在兑现后返回该 Promise 兑现的值。

      function resolveAfter2Seconds(x) {  return new Promise((resolve) => {    setTimeout(() => {      resolve(x);    }, 2000);  });}async function f1() {  let x = await resolveAfter2Seconds(10);  console.log(x); // 10}f1();

      若表达式的值不是 Promise,await 会把该值转换为已兑现的 Promise,然后返回其结果。

      async function f4() {  const y = await Promise.resolve(10);  console.log(y); //10  const obj = {};  console.log((await Promise.resolve(obj)) === obj); // true}f4();

      在模块的顶层,你可以单独使用关键字 await(异步函数的外面)。也就是说一个模块如果包含用了 await 的子模块,该模块就会等待该子模块,这一过程并不会阻塞其他子模块。

      // fetch requestconst colors = fetch("../data/colors.json").then((response) => response.json());export default await colors;

      任何文件只要导入这个模块,后面的代码就会等待,直到 fetch 完成。

      async / await 组合

      单个使用体现不出来它们的强大,组合使用简化了使用基于 promise 的 API 时所需的语法。

      示例:

      async function f3() {  const y = Promise.resolve(10);  const x = await y;  console.log(x); // 10  const z = await 20;  console.log(z); // 20  const obj = {};  console.log((await obj) === obj); // true}console.log(f3());

      工作过程

      每个 await 表达式之后的代码可以被认为存在于 .then 回调中。通过这种方式,可以通过函数的每个可重入步骤来逐步构建 promise 链。而返回值构成了链中的最后一个环。

      示例:

      async function foo() {  const result1 = await new Promise((resolve) =>    setTimeout(() => resolve("1")),  );  const result2 = await new Promise((resolve) =>    setTimeout(() => resolve("2")),  );}foo();
      1. foo 函数的第一行将会同步执行,其中 await 配置了待定的 promise。然后 foo 的进程将被暂停,并将控制权交还给调用 foo 的函数。
      2. 一段时间后,当第一个 promise 被兑现或拒绝的时候,控制权将重新回到 foo 内。在这里 1 被赋值给 result1。程序继续执行,并计算第二个 await 表达式。同样的,foo 的进程将被暂停,并交出控制权。
      3. 一段时间后,当第二个 promise 被兑现或拒绝的时候,控制权将重新回到 foo。在这里 2 被赋值给 result2。程序继续执行到返回表达式(如果有的话)。默认的返回值 undefined 将作为当前 promise 的兑现值被返回。

      promise 链不是一次就构建好的,相反,promise 链是随着控制权依次在异步函数中交出并返回而分阶段构建的。promise是微任务的一种,所以这里体现了事件循环。

      从顶层代码直到(并包括)第一个 await 表达式(如果有的话)都是同步运行的。

      function resolveAfter2Seconds() {  console.log("开始较慢兑现的 promise");  return new Promise((resolve) => {    setTimeout(() => {      resolve("slow");      console.log("较慢兑现的 promise 完成了");    }, 2000);  });}function resolveAfter1Second() {  console.log("开始较快兑现的 promise");  return new Promise((resolve) => {    setTimeout(() => {      resolve("fast");      console.log("较快兑现的 promise 完成了");    }, 1000);  });}async function sequentialStart() {  console.log("== sequentialStart 开始 ==");  // 1. 启动一个计时器,并在计时器完成后打印结果  const slow = resolveAfter2Seconds();  console.log(await slow);  // 2. 等待前一个计时器完成后,启动下一个计时器  const fast = resolveAfter1Second();  console.log(await fast);  console.log("== sequentialStart 结束 ==");}async function sequentialWait() {  console.log("== sequentialWait 开始 ==");  // 1. 启动两个计时器,互不等待  const slow = resolveAfter2Seconds();  const fast = resolveAfter1Second();  // 2. 等待较慢的计时器完成后,打印结果  console.log(await slow);  // 3. 等待较快的计时器完成后,打印结果  console.log(await fast);  console.log("== sequentialWait 结束 ==");}

      sequentialWait()执行2秒,sequentialStart()执行3秒但是它们的结果顺序却相同。

      结语

      有人说async函数是生成器函数的语法糖,仁者见仁,智者见智。

      async函数/await语句和生成器函数(GeneratorFunction)/yield 工作方式比较相似,但两者侧重点和解决问题方向不同,async/await很简单直接,目的在于简化使用基于 promise 的 API 时所需的语法,GeneratorFunction侧重控制函数的执行。

      个人认为async函数不是生成器函数的语法糖,使用生成器可以模仿实现async函数工作,仅此而已。

上一篇:揭秘降幅计算法,轻松掌握高效计算技巧!

下一篇:揭秘连接重置背后的故事