03月31, 2018

如何用原生的js实现一个promise

Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。 一个 Promise有以下几种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

pending 状态的 Promise 对象可能触发fulfilled 状态并传递一个值给相应的状态处理方法,也可能触发失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。

因为Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。

alt

直接上代码

    const PromisePolyfill = (() => {
        //状态管理
        const promiseStatusSymbol = Symbol('PromiseStatus');
        const promiseValueSymbol = Symbol('PromiseValue');
        const STATUS = {
            PENDING: 'PENDING',
            FULFILLED: 'FULFILLED',
            REJECTED: 'REJECTED'
        };
        //resolve操作设置值和状态
        function resolve() {
            this[promiseValueSymbol] = arguments[0];
            this[promiseStatusSymbol] = STATUS['FULFILLED'];
        }
        //reject操作设置值和状态
        function reject() {
            this[promiseValueSymbol] = arguments[0];
            this[promiseStatusSymbol] = STATUS['REJECTED'];
        }

        class myPromise {
            constructor(resolver) {
                if (typeof resolver !== 'function') {
                    throw new TypeError(`parameter 1 must be a function, but get a ${typeof func}`);
                }
                this[promiseStatusSymbol] = STATUS['PENDING'];//初始状态为pending
                resolver(
                    resolve.bind(this),//绑定promise实例对象
                    reject.bind(this)
                );
            }
            then(callback) {
                //开一个定时器监听状态变化,如果有变化则执行callback
                const interval = setInterval(() => {
                    if (this[promiseStatusSymbol] === 'FULFILLED' || this[promiseStatusSymbol] === 'REJECTED') {
                        clearInterval(interval);
                        callback(this[promiseValueSymbol], resolve.bind(this), reject.bind(this));
                        this[promiseStatusSymbol] = 'PENDING';
                //执行完后把状态改回,方便下一个then方法进行定时轮询
                    }
                });
                return this;
            }
        }
        return myPromise;
    })();

测试运行

    //下面会先打印出111,再打印出222,333
    new PromisePolyfill(function (resolve, reject) {
        setTimeout(() => {
            resolve(222);
            console.log(111)
        }, 1000);
    }).then(function (res, resolve, reject) {
        setTimeout(() => {
            resolve(333);
            console.log(res)
        }, 3000);
    }).then(function (res, resolve, reject) {
        console.log(res);
    });

参考文章:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

本文链接:http://www.redtwodog.top/post/前端.html

-- EOF --

Comments