async-await

238 阅读3分钟

async异步函数的声明

  • async定义异步函数(async function someName(){...}) image.png

async异步函数的执行流程

  • async异步函数在没有await时其执行流程和普通函数执行流程一样,

image.png

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

  • 区别一:返回值的区别;async异步函数的返回值一定是一个Promise
async function foo() {
  console.log("foo function start~")
  console.log("中间代码~")
  console.log("foo function end~")

  // 1.返回一个值

  // 2.返回thenable
  // return {
  //   then: function(resolve, reject) {
  //     resolve("hahahah")
  //   }
  // }

  // 3.返回Promise
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // resolve("hehehehe")
      reject(999)
    }, 2000)
  })
}

// 异步函数的返回值一定是一个Promise
foo().then(res => {
  console.log("promise then function exec:", res)
}).catch(err => {
  console.log('err:' + err);        // err:999
})
  • 情况一:异步函数也可以有返回值,但是异步函数的返回值会被包裹到Promise.resolve中;
  • 情况二:如果我们的异步函数的返回值是Promise,Promise.resolve的状态会由Promise决定;
  • 情况三:如果我们的异步函数的返回值是一个对象并且实现了thenable,那么会由对象的then方法来决定;
  • 区别二:函数的异常处理:如果是普通函数代码中出现异常错误后,后续代码不会再被执行,但是当async异步函数抛出错误后,会被.catch()方法捕获,函数后续代码不会受影响。
async function foo() {
  console.log("foo function start~")
  console.log("中间代码~")
  // 异步函数中的异常, 会被作为异步函数返回的Promise的reject值的
  throw new Error("error message")
  console.log("foo function end~")   // 此行代码不管在啥时候都不会执行
}
// 异步函数的返回值一定是一个Promise
foo().catch(err => {
  console.log("err:", err)
})
console.log("后续还有代码~~~~~")  // 此行代码在异步函数中正常执行
// foo function start~
// 中间代码~
// 后续还有代码~~~~~
// err: Error: error message

await关键字

MND

  • async函数另外一个特殊之处就是可以在它内部使用await关键字,而普通函数中是不可以的。也就是说await必须在async异步函数中使用。
  • 如果await后面是一个普通的值,那么会直接返回这个值;
function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  let x = await resolveAfter2Seconds(10);
  console.log(x); // 10
  return 999
}

f1().then((res) => {
  console.log(res);    // 999
})

  • 通常使用await是后面会跟上一个表达式,这个表达式会返回一个Promise; 那么await会等到Promise的状态变成fulfilled状态,之后继续执行异步函数; (await等待的是调用requestData()-resolve的结果,等待成功的结果,在await后面的代码相当于在.then方法里面的代码)
function requestData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(222)
      // reject(1111)
    }, 2000);
  })
}

async function foo() {
  const res1 = await requestData()   // 此行以后的代码相当于.then方法里面代码
  console.log("后面的代码1", res1)     // 后面的代码1 222
}
function requestData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(222)
      // reject(1111)
    }, 2000);
  })
}

async function foo() {
  const res1 = await requestData().then(res => {
    console.log(res);               // 222
  })
  console.log("后面的代码1", res1)    // 后面的代码1 undefined
}
  • 如果await后面的表达式,返回的Promise是reject的状态,那么会将这个reject结果直接作为函数的Promise的 reject值;
function requestData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // resolve(222)
      reject(1111)
    }, 2000);
  })
}

async function foo() {
  const res1 = await requestData()
}

foo().catch(err => {
  console.log("err:", err)    // err: 1111
})
  • 如果await后面是一个thenable的对象,那么会根据对象的then方法调用来决定后续的值;
async function foo() {
  const res1 = await {
    then: function(resolve, reject) {
      // resolve("abc")
      reject('cba')
    }
  }
  console.log(33333);    // 后面两行都没结果
  console.log("res1:", res1)    // res1: abc
  return 222
}

foo().then(res => {
  console.log(res)
}).catch(err => {
  console.log("err:", err)    // err: cba
})

image.png image.png

image.png async函数本身会return一个promise,如果await后面表达式返回一个普通值或者promise是fulfilled状态那么都会打印结果,但是如果是rejected状态那么后续就不会再打印