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)
    })


相关文章
|
5天前
|
前端开发 JavaScript
Promise、async和await
Promise、async和await
11 0
|
1月前
|
前端开发 小程序 API
【微信小程序】-- 使用 npm 包 - API Promise化(四十二)
【微信小程序】-- 使用 npm 包 - API Promise化(四十二)
|
1月前
|
数据采集 前端开发 JavaScript
如何在爬虫过程中正确使用Promise对象和async/await?
如何在爬虫过程中正确使用Promise对象和async/await?
20 2
|
1月前
|
前端开发 JavaScript 开发者
JavaScript 中的异步编程:Promise 和 Async/Await
在现代的 JavaScript 开发中,异步编程是至关重要的。本文将介绍 JavaScript 中的异步编程概念,重点讨论 Promise 和 Async/Await 这两种常见的处理异步操作的方法。通过本文的阐述,读者将能够更好地理解和应用这些技术,提高自己在 JavaScript 开发中处理异步任务的能力。
|
4天前
|
前端开发 JavaScript Java
Promise, async, await实现异步编程,代码详解
Promise, async, await实现异步编程,代码详解
16 1
|
24天前
|
前端开发
promise和async的区别是什么?
promise和async的区别是什么?
9 1
|
1月前
|
存储 前端开发 安全
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索(三)
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索
26 0
|
1月前
|
存储 设计模式 前端开发
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索(二)
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索
30 0
|
1月前
|
并行计算 前端开发 安全
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索(一)
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索
64 0
|
1月前
|
分布式计算 API 数据处理
Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
【2月更文挑战第15天】Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
60 1