JS中的async和await

115 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

异步函数async function

async关键字用于声明一个异步函数:

  • async是asynchronous单词的缩写,异步、非同步;
  • sync是synchronous单词的缩写,同步、同时;

async异步函数可以有很多中写法:

async function bar() {}

const baz = async function () {};

const foo = async () => {};

class Person {
  async fn() {}
}

异步函数的执行流程

  • 异步函数的内部代码执行过程和普通函数是一致的,默认情况下也是被同步执行;
async function bar() {
  console.log("bar exec");
}

console.log("script start");
bar();
console.log("script end");
// script start
// bar exec
// script end
  • 异步函数有返回值时,和普通函数会有区别:

    1. 异步函数的返回值会被包裹到Promise.resolve中;
    2. 如果异步函数的返回值本身是个Promise对象,那么Promise.reolve的状态会由这个Promise对象决定;
    3. 如果异步函数的返回值是一个thenable对象,那么会由该对象的then方法来决定;
async function bar() {
  // 1.返回一个普通值
  // return "hhh";
  // 2.返回一个Promise对象
  // return new Promise((resolve, reject) => {
  //   setTimeout(() => {
  //     resolve("xixixi");
  //   }, 1000);
  // });
  // 3.返回一个thenable对象
  return {
    name: "obj",
    then(resolve) {
      resolve(this.name);
    },
  };
}

const result = bar();
result.then((value) => {
  console.log(value);
});
  • 如果我们在async函数中抛出异常,那么程序并不会像普通函数那样报错,而是作为Promise的reject来传递;
async function foo() {
  console.log("foo start");
  throw "foo err";
  console.log("foo end");
}

const result = foo();
result.catch((reason) => {
  console.log(reason);
});
// foo start
// foo err

await关键字

  • async函数另外一个特殊之处在于它内部能够使用await关键字,而普通函数中是不可以的;

  • await关键字有什么特点呢?

    1. 通常使用await是后面会跟上一个表达式,这个表达式会返回一个Promise;
    2. 那么await会等到Promise的状态变成fulfilled状态,之后继续执行异步函数;
  • 如果await后面是一个普通的值,那么会直接返回这个值;

  • 如果await后面是一个thenable的对象,那么会根据对象的then方法调用来决定后续的值;

  • 如果await后面的表达式,返回的Promise是reject的状态,那么会将这个reject结果直接作为函数的Promise的reject值返回,并且函数会结束执行;

function requestData() {
  return new Promise((resolve, reject) => {
    console.log("request data");
    setTimeout(() => {
      resolve(111);
    }, 1000);
  });
}

async function bar() {
  console.log("bar start");
  const result1 = await requestData();
  // await之后的代码相当于卸载promise.then方法之中
  console.log("result1:", result1);
  const result2 = await requestData();
  console.log("result2:", result2);
  console.log("bar end");
}

console.log("script start");
bar();
console.log("script end");
// script start
// bar start
// request data
// script end
// result1: 111
// request data
// result2: 111
// bar end
async function foo() {
  const result1 = await 111;
  console.log("result1:", result1);
  const result2 = await {
    then(resolve) {
      resolve(222);
    },
  };
  console.log("result2:", result2);
}

console.log("script start");
foo();
console.log("script end");
// script start
// script end  
// result1: 111
// result2: 222
async function baz() {
  console.log("baz start");
  const result = await new Promise((resolve, reject) => {
    reject("bar exec err");
  });
  console.log("result:", result);
  console.log("baz end");
}

baz().catch((reason) => {
  console.log("bar err:", reason);
});
// baz start
// bar err: bar exec err