JS中的async-await

139 阅读4分钟

异步函数 async function

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

  • async是asynchronous单词的缩写,异步、非同步
  • sync是synchronous单词的缩写,同步、同时 异步函数有很多种写法
async function foo(){

}

const foo2 = async () => {

}

class Foo{
  async bar(){
    
  }
}

异步函数的内部代码执行过程和普通的函数是一致的,默认情况下也是会被同步执行。

//这种和普通函数一点区别都没有
async function foo(){
  console.log('foo function start');

  console.log('内部代码执行1');
  console.log('内部代码执行2');
  console.log('内部代码执行3');

  console.log('foo function end');
}

console.log("script start");
foo()
console.log("script end");

只有当异步函数有返回值时,和普通函数会有区别

  • 异步函数也可以有返回值,但是异步函数的返回值会被包裹到Promise.resolve中
  • 如果我们的异步函数的返回值是Promise,Promise.resolve的状态会由Promise决定如果我们的异步函数的返回值是一个对象并且实现了thenable,那么会由对象的then方法来决定
  • 如果我们的异步函数的返回值是一个对象并且实现了thenable,那么会由对象的then方法来决

异步函数与普通函数的区别一 返回值

首先我们要明确一点,调用异步函数时会返回一个promise。

async function f(){
  return 123
}
const promise = f()

我们可以通过异步函数的返回值来调用promise的then方法。

  1. 如果什么都不返回 这种情况就类似我们在函数中return undefined
async function foo(){
  console.log('foo function start ~');
  console.log('中间代码');
  console.log('foo function end ~');
  
  // return undefined 
}

const promise = foo()
promise.then(res => {
  console.log('promise then function exec',res); //promise then function exec undefined
}) 

  1. 返回一个普通的值
async function foo(){
  console.log('foo function start ~');
  console.log('中间代码');
  console.log('foo function end ~');
  
  return 123
}

const promise = foo()
promise.then(res => {
  console.log('promise then function exec',res); //promise then function exec 123
}) 

  1. 返回thenable
async function foo(){
  console.log('foo function start ~');
  console.log('中间代码');
  console.log('foo function end ~');
  
  return {
    then(resolve,reject){
      resolve("hahahah")
    }
  }
}

const promise = foo()
promise.then(res => {
  console.log('promise then function exec',res); //promise then function exec  hahahah
}) 

  1. 返回promise
async function foo(){
  console.log('foo function start ~');
  console.log('中间代码');
  console.log('foo function end ~');
  
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      resolve("hahhaha")
    }, 1000);
  })
}

const promise = foo()
promise.then(res => {
  console.log('promise then function exec',res); //promise then function exec hahhaha
}) 

和普通函数的区别之捕获异常

普通函数

function foo(){
  console.log('foo function start');
  throw new Error("有错误")
}
foo()
console.log('后续还有代码');  //程序直接崩溃了

如果是异步函数

async function foo(){
  console.log('foo function start');
  //异步函数的异常,会被违异步函数返回的Promise的reject值
  throw new Error("有错误")
}

foo().catch(err => {
  console.log('错误是:',err);
})
console.log('后续还有代码'); //这里还会执行

使用await关键字

async函数另外一个特殊之处就是可以在它内部使用await关键字,而普通函数中是不可以的。 await关键字有什么特点呢?

  • 通常使用await是后面会跟上一个表达式,这个表达式会返回一个Promise;

  • 那么await会等到Promise的状态变成fulfilled状态,之后继续执行异步函数

  • 如果await后面是一个普通的值,那么会直接返回这个值

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

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

具体的解释请看下面的代码

async function foo(){
  await 表达式(Promise)
}
function requestData(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      resolve(222)

      // reject("error message")
    },2000)
  })
}

async function foo(){
  const res = await requestData() //等待这个promise指向结束后返回值
  //如果没有结果后面的代码都不会执行
}
function requestData(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      resolve(222)

      // reject("error message")
    },2000)
  })
}

async function foo(){
  const res1 = await requestData() //等待这个promise指向结束后返回值

  //这里的代码相当于promise中的then
  console.log('后面的代码1',res1);
  console.log('接着执行');
}
function requestData(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      resolve(222)

      // reject("error message")
    },2000)
  })
}

async function foo(){
  const res1 = await requestData() //等待这个promise指向结束后返回值
  // 这里后面的多有代码相当于在上面的promise 中then执行
  console.log('第一个promise的then执行');
  console.log(res1);
  const res2 = await requestData()
  console.log('第二个promise的then执行');
  console.log(res2);
}

await后面跟上普通的值

function requestData(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      resolve(222)

      // reject("error message")
    },2000)
  })
}

//跟上其他的值
async function foo(){
  const res1 = await 123  //这里会返回await后面的东西
  console.log('res1:',res1); //res1: 123  
}

foo()

跟上thenable

async function foo(){
  const res1 = await {
    then(resolve,reject){
      resolve("abc")
    }
  }
  console.log(res1); //abc
}

foo()

跟上promise

async function foo(){
    const res1 = await new Promise((resolve) => {
    resolve("harry")
  })
  console.log("res1:",res1); //res1: harry

}

foo()

跟上reject

function requestData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("error message")
    }, 2000)
  })
}

//跟上reject值

async function foo() {
  const res1 = await requestData()
  console.log("res1:", res1);
}

//reject值会当成整个函数的promise
foo().catch(err => {
  console.log('err:',err);
})