异步函数:使 Promise 友好

借助异步函数,您可以编写基于 Promise 的代码,就像它是同步代码一样。

Jake Archibald
Jake Archibald

异步函数在 Chrome、Edge、Firefox 和 Safari 中默认处于启用状态,而且效果非常出色。借助它们,您可以编写基于 Promise 的代码,就像它是同步代码一样,但不会阻塞主线程。它们可使异步代码更易于阅读,并减少“巧妙”的代码。

异步函数的运作方式如下:

async function myFirstAsyncFunction() {
  try {
    const fulfilledValue = await promise;
  } catch (rejectedValue) {
    // …
  }
}

如果您在函数定义之前使用 async 关键字,则可以在函数内使用 await。当您 await 一个 promise 时,该函数会以非阻塞方式暂停,直到 promise 得到解决。如果 promise 执行完毕,您将会收到相应值。如果 promise 被拒绝,则会抛出被拒绝的值。

浏览器支持

Browser Support

  • Chrome: 55.
  • Edge: 15.
  • Firefox: 52.
  • Safari: 10.1.

Source

示例:记录提取操作

假设您要提取网址并将响应记录为文本。使用 promise 时,代码如下所示:

function logFetch(url) {
  return fetch(url)
    .then((response) => response.text())
    .then((text) => {
      console.log(text);
    })
    .catch((err) => {
      console.error('fetch failed', err);
    });
}

下面是使用异步函数实现相同操作的代码:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  } catch (err) {
    console.log('fetch failed', err);
  }
}

行数相同,但所有回调都消失了。这样一来,代码就更容易阅读了,对于不太熟悉 Promise 的用户来说更是如此。

异步返回值

无论您是否使用 await,异步函数都始终返回 Promise。该 Promise 会使用异步函数返回的任何内容进行解析,或使用异步函数抛出的任何内容进行拒绝。因此,使用以下命令:

// wait ms milliseconds
function wait(ms) {
  return new Promise((r) => setTimeout(r, ms));
}

async function hello() {
  await wait(500);
  return 'world';
}

…调用 hello() 会返回一个 promise,该 promise 会使用 "world" 执行

async function foo() {
  await wait(500);