async/await

154 阅读3分钟

一、async/await 是什么

async/await其实是Promise的语法糖,它能实现的效果都能用then链来实现,这也和我们之前提到的一样,它是为优化then链而开发出来的。从字面上来看,async是“异步”的简写,await译为等待,所以我们很好理解async声明function是异步的,await等待某个操作完成。当然语法上强制规定await只能出现在asnyc函数中

二、async/await的作用

  1. async是异步的简写,用于声明一个函数是异步执行。await用于等待一个异步方法执行完毕。
  2. await只能用于async函数中
  3. async 的作用就是将promise和生成器的效果融合了一下,promise主要用于解决回调地狱,也就是将异步代码同步封装。async同样能达到这个效果,而它达成效果依赖的则是生成器的特性。

三、async的使用方法

让我们以 async 这个关键字开始。它可以被放置在一个函数前面,如下所示:

async function f() {
  return 1;
}

在函数前面的 “async” 这个单词表达了一个简单的事情:即这个函数总是返回一个 promise。其他值将自动被包装在一个 resolved 的 promise 中。

例如,下面这个函数返回一个结果为 1 的 resolved promise:

async function f() {
  return 1;
}

f().then(alert); // 1

我们也可以返回一个 promise,结果是一样的:

async function f() {
  return Promise.resolve(1);
}

f().then(alert); // 1

所以说,async 确保了函数返回一个 promise,也会将非 promise 的值包装进去。很简单,对吧?但不仅仅这些。还有另外一个叫 await 的关键词,它只在 async 函数内工作,也非常酷。

四、Await

语法如下:

// 只在 async 函数内工作
let value = await promise;

关键字 await 让 JavaScript 引擎等待直到 promise 完成(settle)并返回结果。

这里的例子就是一个 1 秒后 resolve 的 promise:

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });

let result = await promise; // 等待,直到 promise resolve (*)

  alert(result); // "done!"
}

f();

这个函数在执行的时候,“暂停”在了 (*) 那一行,并在 promise settle 时,拿到 result 作为结果继续往下执行。所以上面这段代码在一秒后显示 “done!”。

让我们强调一下:await 实际上会暂停函数的执行,直到 promise 状态变为 settled,然后以 promise 的结果继续执行。这个行为不会耗费任何 CPU 资源,因为 JavaScript 引擎可以同时处理其他任务:执行其他脚本,处理事件等。

相比于 promise.then,它只是获取 promise 的结果的一个更优雅的语法。并且也更易于读写。

五、总结

函数前面的关键字 async 有两个作用:

  1. 让这个函数总是返回一个 promise。
  2. 允许在该函数内使用 await

Promise 前的关键字 await 使 JavaScript 引擎等待该 promise settle,然后:

  1. 如果有 error,就会抛出异常 —— 就像那里调用了 throw error 一样。
  2. 否则,就返回结果。

这两个关键字一起提供了一个很好的用来编写异步代码的框架,这种代码易于阅读也易于编写。

有了 async/await 之后,我们就几乎不需要使用 promise.then/catch,但是不要忘了它们是基于 promise 的,因为有些时候(例如在最外层作用域)我们不得不使用这些方法。