實現一個簡單的Promise
阿新 • • 發佈:2019-01-27
我們可以在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