promise原理与async 及 await

1.1 Promise是一个构造函数

1 Promise 是一个构造函数
我们可以创建 Promise 的实例 const p = new Promise()
new 出来的 Promise 实例对象,代表一个异步操作
2 Promise.prototype 上包含一个 .then() 方法
每一次 new Promise() 构造函数得到的实例对象,
都可以通过原型链的方式访问到 .then() 方法,例如 p.then()
3 .then() 方法用来预先指定成功和失败的回调函数
p.then(成功的回调函数,失败的回调函数)
p.then(result => { }, error => { })
调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的

1.2 Promise优缺点

缺点
无法取消 Promise,错误需要通过回调函数捕获。
优点
1、当我们在构造 Promise 的时候,构造函数内部的代码是立即执行的(见下面的代码),而返回的结果是异步的Promise
2、Promise`的三种状态分别是:等待中(pending)、完成了 (resolved)、拒绝了(rejected),承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 resolved 后,就不能再次改变

//当我们在构造 Promise的时候,构造函数内部( new Promise)的代码是立即执行的
new Promise((resolve, reject) => {
  console.log('new Promise')
  resolve('success')
}).then(console.log('resolve'))
console.log('finifsh')
//结果 new Promise -> resolve->finifsh

async function fn () {
 	console.log('嘿嘿')
 	const res = await fn2()
	 console.log(res)  // 注意*****微任务,最后输出
}
async function fn2 () {
 	console.log('gaga')
}
fn()
console.log(222)
//嘿嘿->gaga->222->undefine

3、Promise 实现了链式调用,也就是说每次调用 then 之后返回的都是一个 Promise,并且是一个全新的 Promise,原因也是因为状态不可变。如果你在 then 中 使用了 return,那么 return 的值会被 Promise.resolve() 包装(也是‘缺点’)

Promise.resolve(1)
  .then(res => {
    console.log(res) // => 1
    return 2 // 包装成 Promise.resolve(2)
  })
  .then(res => {
    console.log(res) // => 2
  })

在这里插入图片描述
注意:上述的代码无法保证文件的读取顺序,需要做进一步的改进!
在这里插入图片描述

1.3 async 及 await

一个函数如果加上 async ,那么该函数就会返回一个 Promise
async 就是将函数返回值使用 Promise.resolve() 包裹了下,和 then 中处理返回值一样,并且 await 只能配套 async 使用;
因为 await 将异步代码改造成了同步代码(有顺序),如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低
async关键字

  1. async关键字用于声明⼀个异步函数(如 async function asyncTask1() {…})
  2. async会⾃动将常规函数转换成 Promise,返回值也是⼀个 Promise对象
  3. async函数内部可以使⽤ await

await关键字

  1. await用于等待异步的功能执⾏完毕 var result = await someAsyncCall()
  2. await放置在 Promise调⽤之前,会强制async函数中其他代码等待(awiat之后的代码是异步微任务),直到 Promise完成并返回结果
  3. await只能在 async函数内部使⽤
async function test() {
  // 以下代码没有依赖性的话,完全可以使用 Promise.all 的方式
  // 如果有依赖性的话,其实就是解决回调地狱的例子了
  await fetch(url)
  await fetch(url1)
  await fetch(url2)
}
//案例
let a = 0
let b = async () => {
  a = a + await 10
  console.log('2', a) // -> '2' 10
}
b()
a++
console.log('1', a) // -> '1' 1

//输出顺序:1 1->2 10

let a = 0
let b = async () => {
  a = a + await 10
  console.log('2', a) // -> '2' 10
}
b().then(console.log('3', a))
a++
console.log('1', a) // -> '1' 1

//输出顺序:3 0 ->1 1->2 10
//await之后才是微任务
//这里3 0在最前面,表明B直接调用了promise的then原型,a=0
  • 首先函数 b 先执行,在执行到 await 10 之前变量 a 还是 0,因为 await 内部实现了 generatorgenerator 会保留堆栈中东西,所以这时候 a = 0 被保存了下来
  • 因为 await 是异步操作,后来的表达式不返回 Promise 的话,就会包装成 Promise.reslove(返回值),然后会去执行函数外的同步代码
  • 同步代码执行完毕后开始执行异步代码,将保存下来的值拿出来使用,这时候 a = 0 + 10

上述解释中提到了 await 内部实现了 generator,其实 await 就是 generator 加上 Promise 的语法糖,且内部实现了自动执行 generator

1.4 相较于 Promise,async/await有何优势?

1.同步化代码的阅读体验(Promise虽然摆脱了回调地狱,但 then链式调⽤的阅读负担还是存在的)
2.和同步代码更一致的错误处理方式( async/await可以⽤成熟的 try/catch做处理,比 Promise的
错误捕获更简洁直观)
3.调试时的阅读性,也相对更友好

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

waves0001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值