最近在使用ES6,所以手动实现了一个简单的ES6 Promise对象来玩玩(如果有错误的地方,希望大家能够不吝赐教)
一个
promise对象接收的是一个callback
这个callback接收两个参数(resolve,reject)
当我们在callback内执行resolve或reject的时候,就会调用Promise内定义的resolve和reject函数
然后,resolve和reject函数会改变Promise的状态
所以它应该是像下面这样的
function MyPromise(callback) { // 保存this值
var self = this
// 记录状态null为pending,true为resolved,false为reject
var state = null
// 记录resolve的参数
var param = null
// 执行传入的callback并改变promise对象状态
callback(resolve, reject) // resolve方法
function resolve(data) { // 改变状态
state = true
param = data
} // reject方法
function reject(err) {
state = false
param = err
}
}但没有
then方法的Promise对象是不完整的(完全没有用)
所以我们需要一个then方法,要记住then方法返回的也是一个promise对象then方法接收两个可选的参数(onFulfilled, onRejected)(我们可以先忽略可选两个字)then方法传进来的参数必须是函数,如果不是就要忽略(PromiseA+规范)(我们可以也先忽略这句话)
this.then = function (onFulfilled, onRejected) { // 返回一个新的promise对象
return new self.constructor(function (resolve, reject) { // then
})
}接下来就是
then方法的具体实现了then方法中onFulfilled, onRejected的返回值会作为新promise的执行结果
onFulfilled, onRejected这两个函数要在promise的状态变为pending或resolved的时候才能分别执行
所以如果promise方法状态为resolved或rejected的话,我们就可以直接在then方法中执行resolve(onFulfilled(param))和reject(onRejected(param))
this.then = function (onFulfilled, onRejected) { // 返回一个新的promise对象
return new self.constructor(function (resolve, reject) { if (state === true) { // param是promise对象完成后的结果
resolve(onFulfilled(param))
} else if (state === false) {
reject(onRejected(param))
} else { // 没有执行完毕,怎么办
}
})
}但如果
promise的状态为pending呢
由于原始promise的状态我们是无法动态获取的,因此我们就需要在他执行状态改变的时候同时执行onFulfilled和onRejected方法
我们可以把这个方法放在原始promise对象的resolve和reject方法中执行
因此我们要在promise的对象定义中添加四个参数,分别记录onFulfilled和onRejected,以及then方法返回的新promise对象的resolve和reject
然后如果执行then方法的时候promise对象的状态为pending的话,就将上述四个参数记录起来
// then方法返回的promise对象的resolve和rejectvar nextResolve = nullvar nextReject = null// 记录then方法的参数,onFulfilled和onRejectedvar asynconFulfilled = nullvar asynconRejected = null//then方法this.then = function (onFulfilled, onRejected) { // 返回一个新的promise对象
return new self.constructor(function (resolve, reject) { if (state === true) { // param是promise对象完成后的结果
resolve(onFulfilled(param))
} else if (state === false) {
reject(onRejected(param))
} else {
nextResolve = resolve
nextReject = reject
asynconFulfilled = onFulfilled
asynconRejected = onRejected
}
})
}接下来就是原始
promise中的resolve和reject的重新实现
// resolve方法
function resolve(data) { // 改变状态
state = true
param = data
nextResolve(asynconFulfilled(param))
} // reject方法
function reject(err) {
state = false
param = err
nextReject(asynconRejected(param))
}很简单不是吗
我们继续
上述实现我们一直没有考虑一个很重要的情况,如果then方法返回的还是一个promise对象,那么如果我们后边还有then方法的话就要等待前一个then方法中的promise对象的状态从pending变为完成
这要怎么做呢
什么时候可以认为then方法返回的promise对象执行完毕了呢,这里我们就要用到then方法(@_@,边写边用...),
以resolve方法为例
var self = this// resolve方法function resolve(data) { // 记录onFulfilled的执行结果
let parmise // 改变状态
state = true
param = data // 执行记录的onFulfilled
parmise = asynconFulfilled(param) if(parmise === undefined){ // 如果parmise为undefined,就不能解析parmise.constructor
} else if (parmise.constructor === self.constructor) { // 等待传递进来的promise对象执行完毕,然后根据传递进来的promise对象的状态执行resolve或reject
// 注意,这个param是形参,在then方法的promise中执行
promise.then(function (param) {
resolve(param)
}, function (param) {
reject(param)
})
} else { // 这个是前边的then返回的不是promise对象的情况
resolve(promise)
}
}前面我们忽略了两点 (
then方法接收两个可选的参数(onFulfilled, onRejected)) 和 (then方法传进来的参数必须是函数,如果不是就要忽略)
var self = this// resolve方法function resolve(data) { // 记录onFulfilled的执行结果
var parmise // 改变状态
state = true
param = data // 执行记录的onFulfilled
// begin--------------
if (typeof onFulfilled === 'function') {
promise = onFulfilled(param) if (promise === undefined) { // 待补充
} else if (promise.constructor === self.constructor) { // 注意,这个param是形参,在then方法的promise中执行
promise.then(function (param) {
resolve(param)
}, function (param) {
reject(param)
})
} else {
reject(promise)
}
} else { // 如果onFulfilled不是function,忽略,直接resolve或reject
resolve(param)
} // ---------------end}上面begin到end之间的代码还要在
then方法调用,所以我们可以把这段代码抽象为一个函数resolve和reject的原理相同,只要注意如果不是function 的话需要执行reject
onFulfilled和onRejected只有在[执行环境]堆栈仅包含平台代码时才可被调用
所以将上述begin-end之间的代码放到seTimeout中执行(浏览器环境)
function resolve(data) { // 记录onFulfilled的执行结果
var parmise // 改变状态
state = true
param = data // 执行记录的onFulfilled
window.setTimeout(function () { // begin--------------
// 上述代码
// ---------------end
}, 0)
}下面是完整代码
// 简单实现ES6 Promisefunction MyPromise(callback) { // 保存this值
var self = this
// 记录状态null为pending,true为resolved,false为reject
var state = null
// 记录resolve的参数
var param = null
// then方法返回的promise对象的resolve和reject
var nextResolve = null
var nextReject = null
// 记录then方法的参数,onFulfilled和onRejected
var asynconFulfilled = null
var asynconRejected = null
// 执行并改变promise对象状态
callback(resolve, reject) // then方法
this.then = function (onFulfilled, onRejected) { // 返回一个新的promise对象
return new self.constructor(function (resolve, reject) { // 判断异步代码是否执行完毕(是否resolve或reject)
// 若执行完毕就在then方法中立即执行,否则将四个参数记录下来,等待state就绪后再执行doAsyn*函数
if (state === true) {
doAsynconFulfilled(onFulfilled, resolve, reject)
} else if (state === false) {
doAsynconRejected(onRejected, resolve, reject)
} else {
nextResolve = resolve
nextReject = reject
asynconFulfilled = onFulfilled
asynconRejected = onRejected
}
})
} // resolve方法
function resolve(data) { // 改变状态
state = true
param = data if(nextResolve){
doAsynconFulfilled(asynconFulfilled, nextResolve, nextReject)
}
} // reject方法
function reject(err) {
state = false
param = err if(nextReject){
doAsynconRejected(asynconRejected, nextResolve, nextReject)
}
} // 核心方法(我觉得是)
function doAsynconFulfilled(onFulfilled, resolve, reject) { window.setTimeout(function () { // 判断onFulfilled是否为function,不是则忽略
if (typeof onFulfilled === 'function') { // 执行onFulfilled方法获取返回值promise()
let promise = onFulfilled(param) // 如果promise为undefined 执行 if
// 如果promise为MyPromise对象 执行 else if
// 如果promise为非MyPromise对象 执行 else
if (promise === undefined) {
resolve(param) // 待补充
} else if (promise.constructor === self.constructor) { // 等待传递进来的promise对象执行完毕,然后根据传递进来的promise对象的状态执行resolve或reject
promise.then(function (param) {
resolve(param)
}, function (param) {
reject(param)
})
} else { // 执行then方法返回的对象的resolve
resolve(promise)
}
} else { // 传递参数
resolve(param)
}
}, 0)
} function doAsynconRejected(onRejected, resolve, reject) { window.setTimeout(function () { if (typeof onRejected === 'function') { let promise = onRejected(param) if (promise === undefined) {
reject(param) // 待补充
} else if (promise.constructor === self.constructor) {
promise.then(function (param) {
resolve(param)
}, function (param) {
reject(param)
})
} else {
reject(promise)
}
} else { // 传递错误信息
reject(param)
}
}, 0)
}
}// 测试使用var b = function (message) { return new MyPromise(function (resolve, reject) { document.body.onclick = function () {
resolve('click:' + message)
}
})
}var a = new MyPromise(function (resolve, reject) {
resolve(123)
}).then(function (message) { return b(message)
}).then().then(function (message) { console.log('final:' + message)
},function (err) { console.log('final:' + err)
})console.log('window')完毕!
作者:LitCigar
链接:https://www.jianshu.com/p/69dcb2f415dc
随时随地看视频