实现then的流程处理
1、实现promise中同步代码的执行
首先创建一个函数myPromise,传入resolve,reject参数,利用回调函数实现promise中同步代码的执行
function myPromise(fn) {
var resolve = function(Value) {
return Value
}
var reject = function(errValue) {
return errValue
}
if (fn) {
fn(resolve, reject)
}
}
调用函数看结果
var p = new myPromise(function(resolve, reject) {
console.log('我是同步执行的');
})
2、实现promise的状态
promise有三种状态promiseState:
- 初始状态pending
- 成功的状态:fulfilled
- 失败的状态:rejected
PromiseResult属性
- 默认值:undefined
- resolve或 reject 触发时传递的参数
//实现promise的状态和结果(默认)
this.PromiseState = 'pending'
this.PromiseResult = undefined
//更改this指向
let _this = this
var resolve = function(Value) {
//实现promise的状态(resolve)
if (_this.PromiseState === 'pending') { //控制只能执行一次
_this.PromiseState = 'fulfilled'
_this.PromiseResult = Value
}
return Value
}
3、实现resolve执行触发.then()执行
初始化.then()函数
myPromise.prototype.then = function(callback) { }
定义一个函数变量,利用回调函数,使用setTimeout异步执行
this.thenCallback = undefined
var resolve = function(Value) {
//实现promise的状态(resolve)
if (_this.PromiseState === 'pending') { //控制只能执行一次
_this.PromiseState = 'fulfilled'
_this.PromiseResult = Value
//异步执行,肯定在同步执行完成之后执行
setTimeout(function() {
if (_this.thenCallback) {
_this.thenCallback(Value) //执行thenCallback 函数
}
})
}
return Value
}
//实现.then : 初始化.then 函数
myPromise.prototype.then = function(callback) {
// 因为是同步任务,所有resolve之后会将 thenCallback 由 undefine赋值为一个函数
_this.thenCallback = function(value) {
callback(value) //目的是将resolve的参数传递给then作为参数
}
}
4、实现.then().then()...链式调用
当上个then()返回的参数是普通字符串时
myPromise.prototype.then = function(callback) {
//实现链式调用时,每个.then 都应是一个promise对象
return new myPromise(function(resolve, reject) {
// 因为是同步任务,所有resolve之后会将 thenCallback 由 undefine赋值为一个函数
_this.thenCallback = function(value) {
var res = callback(value) //目的是将resolve的参数传递给then作为参数
resolve(res)
}
})
}
当上个then()返回的参数是一个promise对象时
// 当then传入的类型是myPromise对象时;
if (Value instanceof myPromise) {
Value.then(function(res) {
if (_this.thenCallback) {
_this.thenCallback(res)
}
})
} else {
setTimeout(function() {
if (_this.thenCallback) { //添加判断防止没有写.then()的情况
_this.thenCallback(Value) //执行thenCallback 函数
}
})
}
最后调用我们封装的myPromise做测试,查看输出结果
var p = new myPromise(function(resolve, reject) {
resolve('resolve的值')
console.log('我是同步执行的');
})
p.then(function(res) {
console.log("第一个then", res);
return 123
}).then(function(res) {
console.log("第二个then", res);
return new myPromise(function(resolve, reject) {
resolve(456)
})
}).then(function(res) {
console.log("第三个then", res);
return 789
}).then(function(res) {
console.log("第四个then", res);
})
实现catch的流程处理
1、同以上then类似,实现.catch()流程
仿照then的方式在myPromise对象中定义好初始通知函数
this.catchCallback = undefined
var reject = function(errValue) {
if (_this.PromiseState === 'pending') {
_this.PromiseState = 'rejected'
_this.PromiseResult = errValue
}
setTimeout(function() {
if (_this.catchCallback) {
_this.catchCallback(errValue)
} else {
//防止返回reject 但是没有写catch的情况报错
throw ('promise执行了reject,但是没有注册catch!')
}
})
return errValue
}
然后在catch函数中处理
myPromise.prototype.catch = function(callback) {
var _this = this
return new myPromise(function(resolve, reject) {
_this.catchCallback = function(value) {
var err = callback(value)
resolve(err)
}
})
}
2、考虑到.then.catch()中,catch的触发
写完以上的代码会发现,myPromise调用reject的时候,p.catch()执行了,但是p.then().catch()仍然没有执行。
这是因为myPromise调用reject的时候,promise的对象会变更成rejected的状态,并且catch的回调函数无法注册
所以需要追加判断代码让promise值rejected的时候如果没有catchCallback是再去检查是否存在thenCallback
//reject中
setTimeout(function() {
if (_this.catchCallback) {
_this.catchCallback(errValue)
} else if (_this.thenCallback) {
_this.thenCallback(errValue)
} else {
throw ('promise执行了reject,但是没有注册catch!')
}
})
更改then函数中的逻辑
_this.thenCallback = function(value){
//判断如果进⼊该回调时Promise的状态为rejected那么就直接触发后续Promise的catchCallback
//直到找到catch
if(_this.promiseState == 'rejected'){
reject(value) //执行一个catch后就不会在往下执行了
}else{
var callbackRes = callback(value)
resolve(callbackRes)
}
}
3、考虑到链式调用的中断
即考虑 .then中返回promise.reject()的情况
处理 promise返回resolve 时,先执行了.then() , then中返回的new Promise 的 rejected()
更改then中关键代码
if (_this.PromiseState === 'rejected') {
reject(value) //执行一个catch后就不会在往下执行了
} else if (callback) {
var res = callback(value) //目的是将resolve的参数传递给then作为参数
//最后一步:实现then链式调用时某一个then返回promise.reject()中断的情况
if (res instanceof myPromise) {
if (res.PromiseState === 'rejected') {
res.catch(function(errValue) {
reject(errValue)
})
} else {
resolve(res)
}
} else {
resolve(res)
}
}