翻译正在进行中。

 async function 声明将定义一个返回 AsyncFunction 对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的 Promise 返回其结果。但是如果你的代码使用了异步函数,它的语法和结构会更像是标准的同步函数。
 

你还可以使用 异步函数表达式 来定义异步函数。

语法

async function name([param[, param[, ... param]]]) { statements }
name
函数名称。
param
要传递给函数的参数的名称。
statements
函数体语句。

返回值

返回的Promise对象会以async function的返回值进行解析,或者以该函数抛出的异常进行回绝。

描述

当调用一个 async 函数时,会返回一个 Promise 对象。当这个 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。

async 函数中可能会有 await 表达式,这会使 async 函数暂停执行,等待表达式中的 Promise 解析完成后继续执行 async 函数并返回解决结果。

    注意, await 关键字仅仅在 async function中有效。如果在 async function函数体外使用 await ,你只会得到一个语法错误(SyntaxError)。

async/await的用途是简化使用 promises 异步调用的操作,并对一组 Promises执行某些操作。正如Promises类似于结构化回调,async/await类似于组合生成器和 promises。

示例

简单例子

var resolveAfter2Seconds = function() {
  console.log("starting slow promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(20);
      console.log("slow promise is done");
    }, 2000);
  });
};

var resolveAfter1Second = function() {
  console.log("starting fast promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(10);
      console.log("fast promise is done");
    }, 1000);
  });
};

var sequentialStart = async function() {
  console.log('==SEQUENTIAL START==');

  // 如果 await 操作符后的表达式不是一个 Promise 对象, 则它会被转换成一个 resolved 状态的 Promise 对象
  const slow = await resolveAfter2Seconds();

  const fast = await resolveAfter1Second();
  console.log(slow);
  console.log(fast);
}

var concurrentStart = async function() {
  console.log('==CONCURRENT START with await==');
  const slow = resolveAfter2Seconds(); // 立即启动计时器
  const fast = resolveAfter1Second();

  console.log(await slow);
  console.log(await fast); // 等待 slow 完成, fast 也已经完成。
}

var stillSerial = function() {
  console.log('==CONCURRENT START with Promise.all==');
  Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(([slow, fast]) => {
    console.log(slow);
    console.log(fast);
  });
}

var parallel = function() {
  console.log('==PARALLEL with Promise.then==');
  resolveAfter2Seconds().then((message)=>console.log(message)); // in this case could be simply written as console.log(resolveAfter2Seconds());
  resolveAfter1Second().then((message)=>console.log(message));
}

sequentialStart(); // sequentialStart 总共花了 2+1 秒
// 等到 sequentialStart() 完成
setTimeout(concurrentStart, 4000); // concurrentStart 总共花了 2 秒
// 等到 setTimeout(concurrentStart, 4000) 完成
setTimeout(stillSerial, 7000); // stillSerial 总共花了 2 秒
// 等到 setTimeout(stillSerial, 7000) 完成
setTimeout(parallel, 10000); // 真正的并行运行

不要将awaitPromise.then混淆

sequentialStart中,程序为第一个await停留了2秒,然后又为第二个await停留了1秒。直到第一个计时器结束后,第二个计时器才被创建。
在 concurrentStart中,两个计时器均被创建,然后一起被await。这两个计时器同时运行的,但await的调用仍然是按顺序运行的,这意味着第二个await会等到第一个await运行结束。这使得代码完成运行只需要2秒,而不是3秒。这2秒是由最慢的计时器决定的。

使用了Promise.allstillSerial的例子中也存在同样的情况。

如果你希望同时await两个或者是更多的Promise对象,你必须使用Promise.then,正如例子中parallel所做的那样。

通过async方法重写 promise 链

返回 Promise的 API 将会被用于 promise 链,它会将函数分成若干部分。例如下面代码:

function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e => {
      return downloadFallbackData(url)  // 返回一个 promise 对象
        .then(v => {
          return processDataInWorker(v); // 返回一个 promise 对象
        }); 
    })
    .then(v => {
      return processDataInWorker(v); // 返回一个 promise 对象
    });
}

可以通过如下所示的一个async函数重写:

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url); 
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

注意,在上述示例中,return 语句中没有 await 操作符,因为 async function 的返回值将隐式传递给 Promise.resolve

规范

Specification Status Comment
ECMAScript Latest Draft (ECMA-262)
async function
Draft 最初定义于ES2017.
ECMAScript 2017 (ECMA-262)
async function
Standard  

浏览器兼容

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support55 Yes52 No4210.1
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support Yes55 Yes524210.16.0

1. From version 7.0.0: this feature is behind the --harmony runtime flag.

参见

文档标签和贡献者

最后编辑者: NiroDu,