async、await是promise的语法糖,使用async和await,可以让异步代码的书写像同步代码一样。

async关键字

将async关键字放在一个普通的function前面,会变成async function,那么async function和普通的function有什么不一样呢?

function hello() {
  return 'hello'
}
hello()
// "hello"
async function hello() {
  return 'hello'
}
hello()
// Promise {<fulfilled>: "hello"}

从上面的列子可以看出来,当在function 前面加上async后,该函数就会返回一个promise。
异步函数的特征之一就是保证函数的返回值是promise

因为async function的返回值是一个promise,要使用promise完成时的返回值,可以通过.then()进行获取

async function hello() {
  return 'hello'
}
hello().then((str) => alert(str))

await关键字

await关键字需要和async关键字配合使用,也只能在异步函数中才会起作用。await可以放在任何异步的,基于promise的函数之前,它会阻塞代码的执行,知道promise完成,然后返回返回结果值。

async function hello() {
  return new Promise((resolve) => {
    setTimeout(() => {resolve('hello')}, 1000);
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}

sayHello();
// Promise {<pending>}

1s后会弹出“done!”

一些容易出问题的点

Q1:上面说到await会阻塞程序运行,直到异步函数hello()执行出结果,那么如果hello执行的结果是reject或者由于一些问题throw new Error()的话,await后面的代码还会执行吗?
答案:不能执行。

async function hello() {
  return new Promise((resolve, reject) => {
    reject('hello');
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}

sayHello();
// Promise {<rejected>: "hello"}
async function hello() {
  return new Promise((resolve, reject) => {
    throw new Error('hello');
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}

sayHello();
// Promise {<rejected>: Error: hello
    at <anonymous>:3:11
    at new Promise (<anonymous>)
    at hello (<anonymous>:2:1…}

这两个情况下都不会在执行 alert('done!');

如果我们希望hello()运行中执行了reject或者是抛出错误后,不影响后面alert('hello')的执行应该怎么办?增加try catch就行

async function sayHello() {
  try {
    await hello();
  } catch (e) {
    console.log(e)
  }
  alert('done!')
}

Q2:reject或者throw new error的捕获会继续向下传递吗?
答案:会,reject和error会一直冒泡出去

async function hello() {
  return new Promise((resolve, reject) => {
    throw new Error('hello');
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}

sayHello().then((res) => {alert(res), (rej)=>{alert(rej)}})
// Promise {<fulfilled>: undefined}

窗口会弹出“Error: hello”,reject同理,输出“hello”

async function hello() {
  return new Promise((resolve, reject) => {
    throw new Error('hello');
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}
async function catchFunc() {
  try {
    await sayHello()
  } catch(e) {
    alert(e)
  }
}
catchFunc()
// Promise {<fulfilled>: undefined}

窗口会弹出“Error: hello”,reject同理,输出“hello”

Q3:下面两段代码有什么区别
代码片段1

async function hello() {
  return new Promise((resolve, reject) => {
    throw new Error('hello');
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}
async function catchFunc() {
  try {
    sayHello()
  } catch(e) {
    alert(e)
  }
}

catchFunc()
// Promise {<fulfilled>: undefined}

代码片段2:

async function hello() {
  return new Promise((resolve, reject) => {
    throw new Error('hello');
  });
}

async function sayHello() {
  await hello();
  alert('done!')
}
async function catchFunc() {
  try {
    await sayHello()
  } catch(e) {
    alert(e)
  }
}
catchFunc()
// Promise {<fulfilled>: undefined}

答案:代码片段2会弹出“Error:hello”,代码片段1不会。分析的原因应该是代码片段2是在sayHello函数执行完后进行捕获错误,所以可以捕获到错误,代码片段1没有使用await,捕获错误的时候函数sayHello异步执行还没报错,所以不会捕获到。

未完待续...
既然async/await是promise的语法糖,二者怎么转换呢?

async await MDN

03-05 15:57