Promise(简介、基本使用、API、手写实现 Promise、async与await)(三)

简介: Promise(简介、基本使用、API、手写实现 Promise、async与await)(三)

5.2.4 测试

// 成功状态测试
    let p1 = new Promise( (resolve, reject)=>{
      resolve('OK')
    } )
    // p.then(val=>{
    //   console.log(val)
    // }, reason=>{
    //   console.log(reason)
    // })
    console.log(p1)
    // 失败状态测试
    let p2 = new Promise( (resolve, reject)=>{
      reject('error')
    } )
    console.log(p2)
    // 抛出异常测试
    let p3 = new Promise( (resolve, reject)=>{
      throw 'Error'
    } )
    console.log(p3)

会发现Promise的状态和结果没有进行更改

造成的原因:创建Promise对象时,传入的执行器函数为箭头函数,箭头函数没有自己的this,箭头函数的this会指向外层的this。

<body>
  <script>
  let p1 = new Promise( (resolve, reject)=>{
      resolve('OK')
    } )
  </script>
</body>

箭头函数的外层为页面,外层的this指向window,所以箭头函数的this指向window,因此需要想办法让传入执行器为箭头函数this指向Promise对象

5.2.5 保存实例对象的this

// 定义Promise的构造函数
function Promise(excutor) {
  // 定义 PromiseState PromiseResult 
  this.PromiseState = 'pending' // 默认状态 pending
  this.PromiseResult = null // 结果默认为空
  // 在构造 Promise 对象时将 Promise 对象的 this 保存下来
  // 修改时修改 self 上的属性即可,self 指向本对象的this
  // self 就是本对象
  const self = this
  // 定义resolve函数
  function resolve(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
  }
  // 定义reject函数
  function reject(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
  }
  // 捕获 excutor 中的异常并进行处理
  try {
    // 调用传参传过来的执行器函数  同步调用
    excutor(resolve, reject)
  } catch (e) {
    // 处理异常,改变Promise状态为失败,改变结果
    reject(e)
  }
}

5.2.6 再测试

<body>
  <script>
    // 成功状态测试
    let p1 = new Promise( (resolve, reject)=>{
      resolve('OK')
    } )
    // p.then(val=>{
    //   console.log(val)
    // }, reason=>{
    //   console.log(reason)
    // })
    console.log(p1)
    // 失败状态测试
    let p2 = new Promise( (resolve, reject)=>{
      reject('error')
    } )
    console.log(p2)
    // 抛出异常测试
    let p3 = new Promise( (resolve, reject)=>{
      throw 'Error'
    } )
    console.log(p3)
  </script>
</body>

后面补的执行图

5.3 promise.then()的实现

5.3.1 then() 实现

// 定义 Promise 的 then 方法
// 定义在 prototype 上
// then 方法中有两个函数类型的参数 成功状态的回调函数和失败状态的回调函数
Promise.prototype.then = function (onResolved, onRejected) {
  // 根据 Promise 的状态 PromiseState 判断要调用哪个回调函数
  // 状态为成功
  if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
    onResolved( this.PromiseResult )
  }
  // 状态为失败
  if (this.PromiseState === 'rejected') {
    onRejected( this.PromiseResult )
  }
}

then 方法不为箭头函数,为普通函数,有自己的this,指向调用该方法的实例对象

测试:

<body>
  <script>
    // 成功状态测试
    console.log('===== 成功状态测试 =====')
    let p1 = new Promise( (resolve, reject)=>{
      resolve('OK')
    } )
    p1.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })
    console.log(p1)
    // 失败状态测试
    console.log('===== 失败状态测试 =====')
    let p2 = new Promise( (resolve, reject)=>{
      reject('error')
    } )
    p2.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })
    console.log(p2)
    // 抛出异常测试
    console.log('===== 抛出异常测试 =====')
    let p3 = new Promise( (resolve, reject)=>{
      throw 'Error'
    } )
    p3.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })
    console.log(p3)
  </script>
</body>

5.3.2 then() 异步回调执行实现

执行器函数中改为异步任务,会发现没有任何输出

let p1 = new Promise( (resolve, reject)=>{
      setTimeout(()=>{
        resolve('OK')
      }, 500)
    } )
    p1.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })

原因:

所以 then() 中的回调函数并未执行,不会有任何的输出。then() 中缺少对于pending状态时候的判断,需要增加对于pending状态的判断。

// 定义 Promise 的 then 方法
// 定义在 prototype 上
// then 方法中有两个函数类型的参数 成功状态的回调函数和失败状态的回调函数
Promise.prototype.then = function (onResolved, onRejected) {
  // 根据 Promise 的状态 PromiseState 判断要调用哪个回调函数
  // 状态为成功
  if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
    onResolved(this.PromiseResult)
    console.log(this)
  }
  // 状态为失败
  if (this.PromiseState === 'rejected') {
    onRejected(this.PromiseResult)
    console.log(this)
  }
  // 状态为 pending
  if (this.PromiseState === 'pending') {
    // then() 中回调函数执行的时机为 Promise 状态改变之后
    // 所以回调函数应该在状态改变之后进行调用
    // 因此回调函数在resolve或reject函数中转台改变之后进行调用
    // 但是resolve和reject与then为不同的函数,不同的函数作用域
    // 需要将回调函数进行保存后才可以在resolve或reject中进行调用
    // 在构造函数中声明一个对象来保存回调函数
    // 在then()使用其来保存回调函数
    this.callback = {
      onResolved: onResolved,
      onRejected: onRejected
    }
    // 简写
    // this.callback = {
    //   onResolved,
    //   onRejected
    // }
  }
}
// 在构造函数中声明一个回调函数对象用于保存回调函数,
  // 以便在resolve或reject中执行
  this.callback = {}
// 定义Promise的构造函数
function Promise(excutor) {
  // 定义 PromiseState PromiseResult 
  this.PromiseState = 'pending' // 默认状态 pending
  this.PromiseResult = null // 结果默认为空
  const self = this // 将 Promise 对象的 this 保存下来
  // 在构造函数中声明一个回调函数对象用于保存回调函数,
  // 以便在resolve或reject中执行
  this.callback = {}
  // 定义resolve函数
  function resolve(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    // 状态改变之后有成功的回调函数,调用成功的回调函数
    if (self.callback.onResolved) {
      self.callback.onResolved(self.PromiseResult);
    }
  }
  // 定义reject函数
  function reject(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    // 状态改变之后有失败的回调函数,调用失败的回调函数
    if (self.callback.onResolved) {
      self.callback.onResolved(self.PromiseResult);
    }
  }
  // 捕获 excutor 中的异常并进行处理
  try {
    // 调用传参传过来的执行器函数  同步调用
    excutor(resolve, reject)
  } catch (e) {
    // 处理异常,改变Promise状态为失败,改变结果
    reject(e)
  }

测试:

let p1 = new Promise( (resolve, reject)=>{
      setTimeout(()=>{
        resolve('OK')
      }, 500)
    } )
    p1.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })
    let p2 = new Promise( (resolve, reject)=>{
      setTimeout(()=>{
        reject('err')
      }, 500)
    } )
    p2.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })

5.3.3 then() 指定多个回调函数

给p1多指定一个回调函数,会发现只有最后指定的回调函数被执行(原因:后面指定的回调函数覆盖了前面的回调函数)

let p1 = new Promise( (resolve, reject)=>{
      setTimeout(()=>{
        resolve('OK')
      }, 500)
    } )
    p1.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })
    p1.then(val=>{
      console.log(val+'!!!!!!!')
    }, reason=>{
      console.log(reason+'!!!!!!!')
    })

要执行多个回调函数,那么就需要将每个回调函数进行保存,因此改用数组保存回调函数。

this.callback = [] // 声明一个数组用于保存回调函数
• 1
// 状态为 pending
  if (this.PromiseState === 'pending') {
    this.callback.push({
      onResolved: onResolved,
      onRejected: onRejected
    })
  }
// 定义resolve函数
  function resolve(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    self.callback.forEach(item=>{ // 调用所有的回调函数
      item.onResolved(self.PromiseResult)
    });
  }
  // 定义reject函数
  function reject(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    self.callback.forEach(item=>{ // 调用所有的回调函数
      item.onRejected(self.PromiseResult)
    });
  }

完整代码:

// 定义Promise的构造函数
function Promise(excutor) {
  // 定义 PromiseState PromiseResult 
  this.PromiseState = 'pending' // 默认状态 pending
  this.PromiseResult = null // 结果默认为空
  const self = this // 将 Promise 对象的 this 保存下来
  this.callback = [] // 声明一个数组用于保存回调函数
  // 定义resolve函数
  function resolve(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    self.callback.forEach(item=>{ // 调用所有的回调函数
      item.onResolved(self.PromiseResult)
    });
  }
  // 定义reject函数
  function reject(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    self.callback.forEach(item=>{ // 调用所有的回调函数
      item.onRejected(self.PromiseResult)
    });
  }
  // 捕获 excutor 中的异常并进行处理
  try {
    // 调用传参传过来的执行器函数  同步调用
    excutor(resolve, reject)
  } catch (e) {
    // 处理异常,改变Promise状态为失败,改变结果
    reject(e)
  }
}
// 定义 Promise 的 then 方法
// 定义在 prototype 上
// then 方法中有两个函数类型的参数 成功状态的回调函数和失败状态的回调函数
Promise.prototype.then = function (onResolved, onRejected) {
  // 根据 Promise 的状态 PromiseState 判断要调用哪个回调函数
  // 状态为成功
  if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
    onResolved(this.PromiseResult)
    console.log(this)
  }
  // 状态为失败
  if (this.PromiseState === 'rejected') {
    onRejected(this.PromiseResult)
    console.log(this)
  }
  // 状态为 pending
  if (this.PromiseState === 'pending') {
    this.callback.push({
      onResolved: onResolved,
      onRejected: onRejected
    })

测试:

let p1 = new Promise( (resolve, reject)=>{
      setTimeout(()=>{
        resolve('OK')
      }, 500)
    } )
    p1.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })
    p1.then(val=>{
      console.log(val+'!!!!!!!')
    }, reason=>{
      console.log(reason+'!!!!!!!')
    })
    let p2 = new Promise( (resolve, reject)=>{
      setTimeout(()=>{
        reject('err')
      }, 500)
    } )
    p2.then(val=>{
      console.log(val)
    }, reason=>{
      console.log(reason)
    })


相关文章
|
1天前
|
前端开发 JavaScript
在 Vue 中,Promise 和 async/await 有什么不同?
在 Vue 中,Promise 和 async/await 有什么不同?
7 0
|
4天前
|
前端开发 JavaScript API
JavaScript学习笔记(一)promise与async
JavaScript学习笔记(一)promise与async
|
13天前
|
前端开发 JavaScript
JavaScript 中的异步编程:Promise 和 Async/Await 的实现与应用
在Web开发中,JavaScript异步编程是一个不可忽视的重要话题。本文将深入探讨JavaScript中Promise和Async/Await的实现原理与应用场景,通过实例代码带您了解如何优雅地处理异步操作,提升代码的可读性和可维护性。
|
1月前
|
前端开发 JavaScript
处理异步请求的 async/await 和 promise
处理异步请求的 async/await 和 promise
|
2月前
|
前端开发 C++
C++11实用技术(三)std::future、std::promise、std::packaged_task、async
C++11实用技术(三)std::future、std::promise、std::packaged_task、async
17 0
|
2月前
|
JavaScript 前端开发 IDE
Vue3【为什么选择Vue框架、Vue简介 、Vue API 风格 、Vue开发前的准备 、Vue项目目录结构 、模板语法、属性绑定 、 】(一)-全面详解(学习总结---从入门到深化)
Vue3【为什么选择Vue框架、Vue简介 、Vue API 风格 、Vue开发前的准备 、Vue项目目录结构 、模板语法、属性绑定 、 】(一)-全面详解(学习总结---从入门到深化)
38 1
|
2月前
|
前端开发 JavaScript
【面试题】async/await、promise和setTimeout的执行顺序
【面试题】async/await、promise和setTimeout的执行顺序
|
2月前
|
前端开发 JavaScript 开发者
【面试题】前端人70%以上 不了解的promise/async await
【面试题】前端人70%以上 不了解的promise/async await
|
3天前
|
数据采集 监控 安全
各种业务场景调用API代理的API接口教程
API代理的API接口在各种业务场景中具有广泛的应用,本文将介绍哪些业务场景可以使用API代理的API接口,并提供详细的调用教程和代码演示,同时,我们还将讨论在不同场景下使用API代理的API接口所带来的好处。
|
4天前
|
API PHP 开发者
大麦网 API 接口商品详情信息 API
为了让更多用户了解到大麦网的商品详情,并能够方便地获取相关信息,大麦网推出了商品详情 API 接口。本文将介绍大麦网商品详情 API 接口的作用、使用方法和注意事项,帮助广大开发者更加方便地接入大麦网的产品。

相关产品

  • 云迁移中心