async函数和await操作符

85 阅读2分钟

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

async 函数是使用async关键字声明的函数。并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。

async 函数如果没有使用await,那它就相当于一个普通函数,await操作符用于等待一个Promise 对象。await 表达式会暂停当前 async function的执行,等待 Promise 处理完成。若 Promise 正常处理 (fulfilled),其回调的 resolve 函数参数作为 await 表达式的值,继续执行 async function。若 Promise 处理异常 (rejected),await 表达式会把 Promise 的异常原因抛出。另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。

function resolves(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolves(10);
  console.log(x); // 10 resolve 函数参数作为 await 表达式的值
}
f1();

如果await 的表达式不是一个Promise,await 会把该值转换为已正常处理的 Promise,然后等待其处理结果。

async function foo() {
   return 1
}

等价于

function foo() {
   return Promise.resolve(1)
}

async 函数的函数体可以被看作是由 0 个或者多个 await 表达式分割开来的。从第一行代码直到(并包括)第一个 await 表达式(如果有的话)都是同步运行的。这样的话,一个不含 await 表达式的 async 函数是会同步运行的。然而,如果函数体内有一个 await 表达式,async 函数就一定会异步执行。

var fun1 = function() {
    console.log('fun1 start:');
    return new Promise(resolve=>{
      setTimeout(function(){
        resolve('fun1 settime:')
      },2000)
    })
  }
  var fun2 = function() {
    console.log('fun2 start:');
    return new Promise(resolve=>{
      setTimeout(function(){
        resolve('fun2 settime')
      },1000)
    })
  }
  var asyfun = async function() {
    console.log('async start:');
    let one = await fun1() // one = fun1 settime
    
    let two = await fun2() // two = fun2 settime
  }
  asyfun() // async start: // fun1 settime: // fun2 start:
 
  

首先进入函数asyfun() 开始执行,遇见log()函数,直接执行:打印'async start:'。 遇到await会暂停执行后面的代码,开始执行fun1(),console.log('fun1 start:'),然后2s后执行resolve('fun1 settime:')函数,成功返回开始执行fun2(), console.log('fun2 start:');然后1s后执行 fun2()函数resolve()执行成功。整个函数执行完成。