async异步函数与await关键字的详解

一、async、await的原理

我们先看一个需求,然后再一步步推导出async、await的原理

需求:

  • 首先,拿到url后进行异步请求,拿到结果res结果
  • 然后,将res结果拼接'aaa',再进行异步请求,返回res1结果
  • 最后,将res1结果拼接'bbb',再进行异步请求,返回res2结果

代码示例:

有三种解决方案:

方案一:多次回调,会造成回调地狱

requestData('zyk').then(res => {
  requestData(res + 'aaa').then(res => {
    requestData(res + 'bbb').then(res => {
      requestData(res + 'ccc').then(res => {
        console.log(res);
      })
    })
  })
})

方案二:返回一个新的promise,它的resolve决定下一个then的回调函数的值

requestData('zyk').then(res => {
  return requestData(res + 'aaa')
}).then(res => {
  return requestData(res + 'bbb')
}).then(res => {
  return requestData(res + 'ccc')
}).then(res => {
  console.log(res);
})

方案三:Promise + Generator的结合使用

function* getData() {
  const res1 = yield requestData('zyk')
  const res2 = yield requestData(res1 + 'aaa')
  const res3 = yield requestData(res2 + 'bbb')
  const res4 = yield requestData(res3 + 'ccc')
  console.log(res4);
}

const generator = getData()
generator.next().value.then(res => {
  generator.next(res).value.then(res => {
    generator.next(res).value.then(res => {
      generator.next(res).value.then(res => {
        console.log(res);
      })
    })
  })
})

方案四:相当于是Promise + generator的语法糖

async function getData() {
  const res1 = await requestData('zyk')
  const res2 = await requestData(res1 + 'aaa')
  const res3 = await requestData(res2 + 'bbb')
  const res4 = await requestData(res3 + 'ccc')
  console.log(res4);
}

getData()

二、异步函数 asyns function

1.定义

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

执行流程:

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

2.返回值与普通函数的区别

异步函数的返回值一定是一个promise

区别:

  • 情况一:异步函数也可以有返回值,但是异步函数的返回值会被包裹到Promise.resolve中;

  • 情况二:如果我们的异步函数的返回值是Promise,Promise.resolve的状态会由Promise决定;

  • 情况三:如果我们的异步函数的返回值是一个对象并且实现了thenable,那么会由对象的then方法来决定;

代码示例:

async function foo() {
  console.log("start");
  console.log("执行代码");
  console.log("end");

  // 1.返回普通值
  // return 'aaa'

  // 2.是一个对象并且实现了thenable
  // return {
  //   then: function(resolve) {
  //     resolve('bbb')
  //   }
  // }

  // 返回的是一个promise
  return new Promise((resolve, reject) => {
    resolve('ccc')
  })
}

// 异步函数的返回值一定是个promise
const promise = foo()
promise.then(res => {
  console.log("执行代码:", res);
})


处理异常:

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

async function foo() {
  console.log("start");
  console.log("执行代码");

  // 异步函数中的异常 会被作为异步函数返回Promise的reject值
  throw new Error("error message")

  console.log("end");
}

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

console.log("后续的业务代码");

三、await关键字

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

  • await关键字的特点:

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

    • 那么await会等到Promise的状态变成fulfilled状态,之后继续执行异步函数; 后面的代码相当于await返回的promise对象调用then里面需要执行的代码

  • awiait后面表达式的值:

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

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

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

代码示例:

function requestData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // resolve('aaa')
      reject(111)
    },2000)
  })
}

async function foo() {
  // 这个表达式会返回一个Promise
  const res1 = await requestData()
  // 下面的代码相当于上面的await返回的promise.then里面执行的代码
  console.log("后面的代码", res1);
}

foo()

// 2.其他值
async function foo() {
  // 2.1 普通值
  const res1 = await 'abc'
  console.log("后面的代码", res1);

  // 2.2 对象并且实现thenable
  const res2 = await {
    then: function(resolve, reject) {
      resolve("aaa")
    }
  }
  console.log(res2);

  // 2.3 Promise
  const res3 = await new Promise(resolve => {
    resolve("zyk")
  })
  console.log(res3);
}

foo()

await后面的promise如果返回reject,那么就需要在async函数返回值使用catch捕获错误,然后继续执行后面的代码

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

foo().catch(err => {
  console.log(err);
})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值