Promise实现原理

new Promise((resolve, reject) => {})

Promise的内部状态和值

PromiseStatus:

  • PENDING
  • FULFILLED
  • REJECTED

状态的只能在pending时由resolve和reject改变为fulfilled或rejected

PromiseValue:

  • resolve和reject所接收的参数

状态和值的修改

状态常量:

const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

内部的_resolve和_reject -> 改变状态和存储值:

run(status, value) {
    this.PromiseStatus = status
    this.PromiseValue = value
}

_resolve(value) {
    if (this.PromiseStatus !== PENDING) return
    this.run(FULFILLED, value, this.FulfilledQueues)
}

_reject(error) {
    if (this.status !== PENDING) return
    this.run(REJECTED, error, this.RejectedQueues)
}

promise的then

promise.then(onFulfilled, onRejected)

then的两个参数皆是回调函数,若不是,则忽略

then的特征:

  • onFulfilled在fulilled状态被调用,onRejected在rejected状态被调用
  • 支持链式调用,且依次回调,即回调返回promise并且有专门的执行队列来管理回调
  • pending时不可调用,加入队列

定义status、value、回调管理队列,new 的时候执行handller:

export class FakePromise {
    constructor(handller) {
        if (!(handller instanceof Function)) throw new Error('Mypromise must accept a functio as a parameter')
        Object.defineProperties(this, {
            PromiseStatus: {
                writable: true,
                value: PENDING
            },
            PromiseValue: {
                writable: true,
            },
            FulfilledQueues: {
                writable: true,
                value: []
            },
            RejectedQueues: {
                writable: true,
                value: []
            }
        })
        try {
            handller(this._resolve.bind(this), this._reject.bind(this))
        } catch (error) {
            handller(this._reject.bind(this))
        }
    }
}

所以then大概有这么个意思:

then(onFulfilled, onRejected) {
  const { PromiseStatus, PromiseValue } = this
  switch(PromiseStatus) {
    // 当状态为pending时,将then方法回调函数加入执行队列等待执行
    case PENDING:
      this.FulfilledQueues.push(onFulfilled)
      this.RejectedQueues.push(onRejected)
      break
    case FULFILLED:
      onFulfilled(PromiseValue)
      break
    case REJECTED:
      onRejected(PromiseValue)
      break
  }
  return new MyPromise((resolveNext, rejectNext) => {
  })
}

handller内部执行(异步或者同步)到resolve或reject执行时要保证onFulfilled或者onRejected被调用(单个或者多个),则在then内部执行时,需要在恰当的时机想队列中添加回调,resolve或者reject时从队列中取得。 完善_resolve和_reject

run(status, value, queues) {
    this.PromiseStatus = status
    this.PromiseValue = value

    let callback
    while (callback = queues.shift()) {
        callback(value)
    }
}

_resolve(value) {
    if (this.PromiseStatus !== PENDING) return
    if (value instanceof FakePromise) {
        return value.then(this._resolve.bind(this), this._reject.bind(this))
    }
    // 为了支持同步的promise,即让同步的promise.then在同步代码最后执行
    setTimeout(() => {
        this.run(FULFILLED, value, this.FulfilledQueues)
    }, 0)
}

_reject(error) {
    if (this.status !== PENDING) return
    setTimeout(() => {
        this.run(REJECTED, error, this.RejectedQueues)
    }, 0)
}

then返回的promise对象状态的改变,依赖于当前then的参数,是否为函数,返回是否是promise,而参数回调的执行也依赖当前promise的状态
完善then:

then(onFulfilled, onRejected) {
    const { PromiseStatus, PromiseValue } = this
    // 返回promise
    return new FakePromise((resolveNext, rejectNext) => {
        const fulfilled = value => {
            try {
                if (!(onFulfilled instanceof Function)) {
                    // 不是函数是乡下传递上一个返回的promise
                    resolveNext(value)
                } else {
                    const res = onFulfilled(value)
                    // 根绝函数返回结果,判断下个then传递什么
                    if (res instanceof FakePromise) {
                        res.then(resolveNext, rejectNext)
                    } else {
                        resolveNext(res)
                    }
                }
            } catch (error) {
                // 异常处理
                rejectNext(error)
            }
        }
        const rejected = error => {
            try {
                if (!(onRejected instanceof Function)) {
                    rejectNext(error)
                } else {
                    let res = onRejected(error)
                    if (res instanceof MyPromise) {
                        res.then(resolveNext, rejectNext)
                    } else {
                        resolveNext(res)
                    }
                }
            } catch (err) {
                rejectNext(err)
            }
        }
        // 函调函数的统一处理
        switch (PromiseStatus) {
            case PENDING:
                this.FulfilledQueues.push(fulfilled)
                this.RejectedQueues.push(rejected)
                break
            case FULFILLED:
                fulfilled(PromiseValue)
                break
            default: rejected(PromiseValue)
        }
    })
}

Promise的完整代码

const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

export class FakePromise {
    static resolve(value) {
        if (value instanceof FakePromise) return value
        return new FakePromise(resolve => resolve(value))
    }
    static reject(error) {
        return new FakePromise((resolve, reject) => reject(error))
    }
    static race(iterable) {
        return new FakePromise((resolve, reject) => {
            for (let p of iterable) {
                this.resolve(p).then(resolve, reject)
            }
        })
    }
    static all(iterable) {
        return new FakePromise((resolve, reject) => {
            const values = []
            let count = 0
            for (let [i, p] of iterable.entries()) {
                this.resolve(p).then(
                    res => {
                        values[i] = res
                        count++
                        if (count === iterable.length) resolve(values)
                    },
                    reject
                )
            }
        })
    }

    toString() {
        return '[object Promise]'
    }

    constructor(handller) {
        if (!(handller instanceof Function)) throw new Error('Mypromise must accept a functio as a parameter')

        Object.defineProperties(this, {
            PromiseStatus: {
                writable: true,
                value: PENDING
            },
            PromiseValue: {
                writable: true,
            },
            FulfilledQueues: {
                writable: true,
                value: []
            },
            RejectedQueues: {
                writable: true,
                value: []
            }
        })

        try {
            handller(this._resolve.bind(this), this._reject.bind(this))
        } catch (error) {
            handller(this._reject.bind(this))
        }
    }


    run(status, value, queues = []) {
        this.PromiseStatus = status
        this.PromiseValue = value

        let callback
        while (callback = queues.shift()) {
            callback(value)
        }
    }

    _resolve(value) {
        if (this.PromiseStatus !== PENDING) return
        if (value instanceof FakePromise) {
            return value.then(this._resolve.bind(this), this._reject.bind(this))
        }
        setTimeout(() => {
            this.run(FULFILLED, value, this.FulfilledQueues)
        }, 0)
    }

    _reject(error) {
        if (this.status !== PENDING) return
        setTimeout(() => {
            this.run(REJECTED, error, this.RejectedQueues)
        }, 0)
    }

    then(onFulfilled, onRejected) {
        const { PromiseStatus, PromiseValue } = this

        return new FakePromise((resolveNext, rejectNext) => {

            const fulfilled = value => {
                try {
                    if (!(onFulfilled instanceof Function)) {
                        resolveNext(value)
                    } else {
                        const res = onFulfilled(value)
                        if (res instanceof FakePromise) {
                            res.then(resolveNext, rejectNext)
                        } else {
                            resolveNext(res)
                        }
                    }
                } catch (error) {
                    rejectNext(error)
                }
            }

            const rejected = error => {
                try {
                    if (!(onRejected instanceof Function)) {
                        rejectNext(error)
                    } else {
                        let res = onRejected(error)
                        if (res instanceof MyPromise) {
                            res.then(resolveNext, rejectNext)
                        } else {
                            resolveNext(res)
                        }
                    }
                } catch (err) {
                    rejectNext(err)
                }
            }

            switch (PromiseStatus) {
                case PENDING:
                    this.FulfilledQueues.push(fulfilled)
                    this.RejectedQueues.push(rejected)
                    break
                case FULFILLED:
                    fulfilled(PromiseValue)
                    break
                default: rejected(PromiseValue)
            }
        })
    }

    catch(onRejected) {
        return this.then(undefined, onRejected)
    }

    finally(callback) {
        return this.then(
            result => FakePromise.resolve(callback()).then(() => result),
            error => FakePromise.resolve(callback()).then(() => { throw error })
        )
    }
}
FakePromise

console结果可能不准确,按F12打开控制台查看