初探Promise

107 阅读3分钟

Promise/A+规范

  1. new Promise时,需要传递一个 executor 执行器,执行器立刻执行
  2. executor 接受两个参数,分别是 resolve 和 reject
  3. promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
  4. promise 的状态一旦确认,就不会再改变
  5. promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 和 promise 失败的回调 onRejected
  6. 如果调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值作为参数传递进去。
  • 如果promise已经失败,那么执行 onRejected, 并将 promise 失败的原因作为参数传递进去。
  • 如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(发布订阅)
  1. then 的参数 onFulfilled 和 onRejected 可以缺省
  2. promise 可以then多次,promise 的then 方法返回一个 promise
  3. 如果 then 返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功的回调(onFulfilled)
  4. 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调(onRejected) 11.如果 then 返回的是一个promise,那么需要等这个promise,那么会等这个promise执行完,promise如果成功,就走下一个then的成功,如果失败,就走下一个then的失败

A+下的基本功能实现

/**
 * 自定义Promise函数模块
 */
(function () {
    // Promise的三种状态
    const PENDING = 'pending' // 未决
    const RESOLVED = 'fulfilled' // 成功
    const REJECTED = 'rejected' // 拒绝

    /**
     * Promise构造函数
     * @param {*} executor 执行器函数
     */
    function Promise(executor) {
        const self = this
        // 给promise对象指定status属性,初始值为pending
        self.status = PENDING
        // 给promise对象指定一个用于存储结果数据的属性
        self.data = undefined
        // 每个元素的结构 { onResolved(){}, onRejected() }
        self.callbacks = []


        function resolve(value) {
            // 此处做判断,使得promise的状态只能修改一次
            if (self.status === PENDING) {
                // 将状态改为 resolved
                self.status = RESOLVED
                // 保存value数据
                self.data = value

                // 如果有待执行的callback函数,立即异步执行回调
                if (self.callbacks.length > 0) {
                    setTimeout(() => { // 表示在异步队列中执行
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onResolved(value)
                        })
                    }, 0);
                }
            }
        }
        function reject(reason) {
            // 此处做判断,使得promise的状态只能修改一次
            if (self.status === PENDING) {
                // 将状态改为 resolved
                self.status = REJECTED
                // 保存value数据
                self.data = reason

                // 如果有待执行的callback函数,立即异步执行回调
                if (self.callbacks.length > 0) {
                    setTimeout(() => { // 表示在异步队列中执行
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onRejected(reason)
                        })
                    }, 0);
                }
            }
        }

        // 立即执行器
        try {
            executor(resolve, reject);
        } catch (error) { // 如果执行器抛出异常,promise状态变为rejected状态
            reject(error)
        }
    }

    /**
     * Promise原型对象的then方法
     */
    Promise.prototype.then = function (onResolved, onRejected) {
        const self = this
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        return new Promise((resolve, reject) => {
            if (self.status === RESOLVED) {
                setTimeout(() => {
                    const value = onResolved(self.data)
                    resolve(value)
                }, 0);
            } else if (self.status === REJECTED) {
                setTimeout(() => {
                    const reason = onRejected(self.data)
                    reject(reason)
                }, 0);
            } else {
                self.callbacks.push({
                    onResolved(value) {
                        resolve(value)
                    },
                    onRejected(reason) {
                        reject(reason)
                    }
                })
            }
        })
    }

    /**
     * Promise原型对象的catch方法
     */
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
    }

    /**
     * Promise的静态方法
     */
    // resolve
    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(resolve, reject)
            } else {
                resolve(value)
            }
        })
    }
    // reject
    Promise.reject = function (reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }
    // all
    Promise.all = function (promises) {
        if (!(promises instanceof Array)) {
            return Promise.reject(new Error('params must be a Array!'))
        }
        // 保存成功的value
        const result = new Array(promises.length)
        // 计算成功的数量
        let count = 0
        return new Promise((resolve, reject) => {
            // 遍历获取每个promise的结果
            promises.forEach((p, index) => {
                Promise.resolve(p).then(value => { // onFulfilled
                    count++
                    result[index] = value
                    if (resultCount === promises.length) { // 全部成功,resolve结果
                        resolve(resul)
                    }
                }, reason => { // onRejected
                    reject(reason)
                })
            })
        })
    }
    // race
    Promise.race = function (promises) {
        if (!(promises instanceof Array)) {
            return Promise.reject(new Error('params must be a Array!'))
        }

        return new Promise((resolve, reject) => {
            // 遍历数组
            promises.forEach((p, index) => {
                Promise.resolve(p).then(value => {
                    resolve(value)
                }, reason => {
                    reject(reason)
                })
            })
        })
    }
    
    // 向外暴露函数
    window.Promise = Promise
})(window)