我们可以在chrome开发工具下看下原生 promise
是什么:
new Promise((resolve, reject) => {})
return Promise {
[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined
}
可以看出Promise
实例有两个property,一个表示status一个为value
所以我们可以这样写Promise构造函数
var PENDING = 'pending'
var FULFILLED = 'resolved'
var REJECTED = 'rejected'
function MyPromise(fn) {
if (typeof fn !== 'function') throw new TypeError('not a function')
// init property
this.status = PENDING
this.value = undefined
// 因为每当我们new Promise(fn) fn是立即执行的, 所以我们调用doHandle来处理fn,因为status一旦改变,就不能再变
doHandle(this, fn)
}
我们写一个来处理fn
的函数,并控制逻辑
function doHandle(self, fn) {
var done = false // 闭包
fn(function(value) {
if (done) return
done = true
// resolve
resolve(self, value)
}, function(reason) {
if (done) return
done = true
// reject
reject(self, reason)
})
}
resolve
和 reject
用来分别处理不同状态
function resolve(self, value) {
try {
self.status = FULFILLED
self.value = value
} catch (e) {
reject(self, e)
}
}
function reject(self, reason) {
self.status = REJECTED
self.value = reason
}
我们已经写好了promise
的状态改变,接下来完成 then
来完成异步操作
MyPromise.prototype.then = function(onFulFilled, onRejected) {
var promise = new (this.constructor)(function() {})
// 处理如何异步
handle(this, onFulFilled, onRejected, promise)
// chain object
return promise
}
// 异步, most important
var immediateFn = (typeof setImmediate === 'function' && function(fn) { setImmediate(fn) }) || function(fn) {
setTimeout(fn, 0)
}
function handle(self, onFulFilled, onRejected, promise) {
immediateFn(function() {
var cb = self.status === FULFILLED ? onFulFilled : onRejected
if (cb === null) {
(self.status=== FULFILLED ? resolve : reject)(promise, self.value)
return
}
cb(self.value)
})
}
好了,大功告成,可以Test