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