javascript|promise原理与async 及 await


promise原理与async 及 await

      • 1.1 Promise是一个构造函数
      • 1.2 Promise优缺点
      • 1.3 async 及 await
      • 1.4 相较于 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->finifshasync 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 })

javascript|promise原理与async 及 await
文章图片

注意:上述的代码无法保证文件的读取顺序,需要做进一步的改进!
javascript|promise原理与async 及 await
文章图片

1.3 async 及 await
【javascript|promise原理与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 10let 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.调试时的阅读性,也相对更友好

    推荐阅读