1. 程式人生 > >實現一個簡單的Promise

實現一個簡單的Promise

promise工作機制圖解

我們可以在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) }) }

resolvereject

用來分別處理不同狀態

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