JS查漏补缺——async-await

74 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

async异步函数

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

// 写法一:
async function foo1() {

}
// 写法二:
const foo2 = async () => {

}
// 写法三:
class Foo {
  async bar() {

  }
}

async异步函数与普通函数的区别

1. 返回值

async 函数一定会返回一个 promise 对象。

如果一个 async 函数的返回值看起来不是 promise,那么它将会被隐式地包装在一个 promise 中。

2. 异常

普通函数:

function foo() {
  console.log("foo function start~")
  console.log("中间代码~")
  throw new Error("error message")
  console.log("foo function end~")
}
foo().catch(err => {
  console.log("error message:", err)
})
console.log("后续还有代码~~~~~")
// 输出抛出异常前面的代码并抛出异常,后面代码不执行

异步函数:

async function foo() {
  console.log("foo function start~")
  console.log("中间代码~")
  // 异步函数中的异常, 会被作为异步函数返回的Promise的reject值的
  throw new Error("error message")
  console.log("foo function end~")
}
foo().catch(err => {
  console.log("error message:", err)
})
console.log("后续还有代码~~~~~")
// 后续代码会被执行,之后打印错误信息

如果我们在async中抛出了异常,那么程序它并不会像普通函数一样报错,而是会作为Promise的reject来传递;

await关键字

await 表达式会暂停整个 async 函数的执行进程并出让其控制权,只有当其等待的基于 promise 的异步操作被兑现或被拒绝之后才会恢复进程。promise 的解决值会被当作该 await 表达式的返回值

注意:await关键字只在 async 函数内有效。如果你在 async 函数体之外使用它,就会抛出语法错误。

async/await搭配使用:

function requestData1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1111)
    }, 2000);
  })
}

function requestData2() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(222)
    }, 3000);
  })
}

async function foo1() {
  // 1.await跟上表达式
  const res1 = await requestData1()
  // 2. await跟上其他值
  const res2 = await 123  // "await" 对此表达式的类型没有影响
  console.log("后面的代码1", res1) 
  console.log("后面的代码2", res2)
}
foo1()

// 3.reject值
async function foo2() {
  const res3 = await requestData2()
  console.log("res3:", res3)
}

foo2().catch(err => {
  console.log("err:", err)
})

当await后面跟着是reject值,则它返回的值会作为整个foo2返回的Promise值,await之后的代码不会执行

总结:

async/await的目的为了简化使用基于 promise 的 API 时所需的语法(promise语法糖)。

async/await的行为就好像搭配使用了生成器和 promise。