资讯专栏INFORMATION COLUMN

自己照着Promise/A规范写的Promise库

Render / 3413人阅读

摘要:试图写了一下大概测试了一下没有用专业的测试工具测试代码感觉还是写的比较好懂的,本人水平较差,如果测试有问题,欢迎回复指出地址同一执行队列中原生是先于实现的自己实现暂时用模拟必须传入并且构造状态改变之后传递的值执行之后返回的这里必须异步处理否

试图写了一下,大概测试了一下,没有用专业的测试工具测试....

代码感觉还是写的比较好懂的,本人水平较差,如果测试有问题,欢迎回复指出
地址: https://github.com/julyL/Code...

(function(global) {
    function isFunction(val) {
        return typeof val == "function";
    }

    function isObject(val) {
        return typeof val == "object";
    }

    function asyncExcute(fn) {
        return function() {
            setTimeout(fn); // 同一执行队列中,原生Promise是先于setTimeout实现的,自己实现暂时用setTimeout模拟
        }
    }
    function Promise(fn) {
        if (!isFunction(fn) || this instanceof Promise == false) {
            throw new TypeError("Promise必须传入function并且new构造")
        }
        this.status = "pending";
        this.value = undefined; //  promise状态改变之后传递的值
        this.thenPromise = undefined; //执行then之后返回的promise
        this.resolveQueue = []; //
        this.rejectQueue = []; //   
        var re = asyncExcute(function(resolveData) { this._resolve(resolveData) }.bind(this)), //这里必须异步处理,否则then函数执行以前可能就已经执行了_resolve,但这时then中函数还未加入resolveQueue中
            rj = asyncExcute(function(resolveData) { this._reject(resolveData) }.bind(this));
        try {
            fn(re, rj)
        } catch (error) {
            this.status = "reject";
            this.value = error;
            asyncExcute(function(){this._reject(error)});         //  new Promise(()=>{ 出现异常... }).then(refn,rjfn);    出现异常时then还未执行, rjfn还未加入到rejectQueue中  
        }
    }
    Promise.prototype.then = function(refn, rjfn) {
        var returnPro = new Promise(function() {});
        this.thenPromise = returnPro;
        this.resolveQueue.push(refn);
        this.rejectQueue.push(rjfn);

        if (this.status == "resolve") { //执行then时,如果状态已经不是pending,则执行相应函数
            this._resolve(this.value);
        }
        if (this.status == "reject") {
            this._reject(this.value);
        }
        return returnPro;
    }
    Promise.prototype._resolve = function(resolveData) {
        var handle,
            returnVal;
        this.status = "resolve";
        this.value = resolveData;
        while (this.resolveQueue.length > 0) { //2.2.6  当 promise 成功执行时,所有 onFulfilled 需按照其注册顺序依次回调
            handle = this.resolveQueue.shift();
            if (!isFunction(handle)) { //不是函数  2.1.1 onFulfilled 不是函数,其必须被忽略
                this.thenPromise.value = resolveData;
                this.thenPromise.status = "resolve";
                this.thenPromise._resolve();
                return;
            }
            try { //如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
                returnVal = handle(resolveData);
            } catch (error) {
                this.thenPromise.status = "reject";
                this.thenPromise.value = error;
                this.thenPromise._reject();
            }
            if (isObject(returnVal || isFunction(returnVal))) { //如果返回值为对象或者函数
                if (returnVal == this.thenPromise) { //如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
                    this.thenPromise.status = "reject";
                    this.thenPromise.value = new TypeError("[[Resolve]](promise, x),promise 和 x 不能指向同一对象");
                } else if (returnVal instanceof Promise) { //如果 x 为 Promise ,则使 promise 接受 x 的状态
                    try {
                        then.call(returnVal, this.thenPromise._resolve.bind(this.thenPromise), this.thenPromise._reject.bind(this.thenPromise));
                    } catch (error) {
                        this.thenPromise.status = "reject";
                        this.thenPromise.value = error;
                        this.thenPromise._reject();
                    }
                } else { //如果 x 为对象或者函数
                    try { //如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
                        var then = returnVal.then;
                        if (isFunction(then)) {
                            then.call(returnVal, this.thenPromise._resolve.bind(this.thenPromise), this.thenPromise._reject.bind(this.thenPromise));
                        }
                    } catch (error) {
                        this.thenPromise.status = "reject";
                        this.thenPromise.value = error;
                        this.thenPromise._reject();
                    }
                }
            } else {
                this.thenPromise.value = returnVal;
                this.thenPromise.status = "resolve";
                this.thenPromise._resolve();
            }
        }
    }

    Promise.prototype._reject = function(resolveData) {
        var handle,
            returnVal;
        this.status = "resolve";
        this.value = resolveData;
        while (this.rejectQueue.length > 0) {     //2.2.6  当 promise 成功执行时,所有 onFulfilled 需按照其注册顺序依次回调
            handle = this.rejectQueue.shift();
            if (!isFunction(handle)) {          //不是函数  2.1.1 onFulfilled 不是函数,其必须被忽略
                this.thenPromise.value = resolveData;
                this.thenPromise.status = "resolve";
                this.thenPromise._resolve();
                return;
            }
            try { //如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
                returnVal = handle(resolveData);
            } catch (error) {
                this.thenPromise.status = "reject";
                this.thenPromise.value = error;
                this.thenPromise._reject();
            }
            if (isObject(returnVal || isFunction(returnVal))) { //如果返回值为对象或者函数
                if (returnVal == this.thenPromise) { //如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
                    this.thenPromise.status = "reject";
                    this.thenPromise.value = new TypeError("[[Resolve]](promise, x),promise 和 x 不能指向同一对象");
                } else if (returnVal instanceof Promise) { //如果 x 为 Promise ,则使 promise 接受 x 的状态
                    try {
                        then.call(returnVal, this.thenPromise._resolve.bind(this.thenPromise), this.thenPromise._reject.bind(this.thenPromise));
                    } catch (error) {
                        this.thenPromise.status = "reject";
                        this.thenPromise.value = error;
                        this.thenPromise._reject();
                    }
                } else {      //如果 x 为对象或者函数
                    try {     //如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
                        var then = returnVal.then;
                        if (isFunction(then)) {
                            then.call(returnVal, this.thenPromise._resolve.bind(this.thenPromise), this.thenPromise._reject.bind(this.thenPromise));
                        }
                    } catch (error) {
                        this.thenPromise.status = "reject";
                        this.thenPromise.value = error;
                        this.thenPromise._reject();
                    }
                }
            } else {
                this.thenPromise.value = returnVal;
                this.thenPromise.status = "resolve";
                this.thenPromise._resolve();
            }
        }
    }

    Promise.resolve = function(value) {
        return new Promise(function(re, rj) {
            re(value)
        })
    }
    Promise.reject = function(value) {
        return new Promise(function(re, rj) {
            re(value)
        })
    }
    Promise.all = function(queue) {
        if (Object.prototype.toString.call(queue) != "[object Array]") {
            return;
        }
        var returnPromise = new Promise(function() {}),
            resolveNum = 0;
        for (var i = 0; i < queue.length; i++) {
            queue[i].then(function() {
                resolveNum++;
                if (resolveNum == queue.length) {
                    returnPromise._resolve();
                }
            });
        }
        return returnPromise;
    }
    Promise.race = function(queue) {
        if (Object.prototype.toString.call(queue) != "[object Array]") {
            return;
        }
        var returnPromise = new Promise(function() {}),
            resolveNum = 0;
        for (var i = 0; i < queue.length; i++) {
            queue[i].then(function() {
                returnPromise._resolve();
            });
        }
        return returnPromise;
    }
    global.Promise = Promise;
})(window);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82593.html

相关文章

  • 一步一步实现一个符合PromiseA+规范Promise(1)

    摘要:今天我们来自己手写一个符合规范的库。是异步编程的一种解决方案,比传统的解决方案回调函数和事件更合理和更强大。我们可以看到,其实就是一个构造函数。所以说我们的数组里存的是一个一个的的回调函数,也就是一个一个。 今天我们来自己手写一个符合PromiseA+规范的Promise库。大家是不是很激动呢?? showImg(https://segmentfault.com/img/bV6t4Z?...

    joyvw 评论0 收藏0
  • 一步步写一个符合Promise/A+规范

    摘要:本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。中采用了规范,实现之前,当然要先了解规范,规范地址。我们根据规范,可以写一个简单的库。每一步都尽量写的详细,所以代码很长很罗嗦。 Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 ES6 中采用了 Promise/A+ 规范,Promise 实现之前,当然要先了解 Promise/A+ 规范,...

    econi 评论0 收藏0
  • JavaScript 异步

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。写一个符合规范并可配合使用的写一个符合规范并可配合使用的理解的工作原理采用回调函数来处理异步编程。 JavaScript怎么使用循环代替(异步)递归 问题描述 在开发过程中,遇到一个需求:在系统初始化时通过http获取一个第三方服务器端的列表,第三方服务器提供了一个接口,可通过...

    tuniutech 评论0 收藏0
  • 手写一个符合A+规范Promise

    摘要:本文同时也发布在我的博客上,欢迎之前也手写过简单的,这次则是为了通过官方的测试集,借鉴了一些下载量较多的,改了几遍,终于是通过了规范的个测试用例如何测试测试库地址在这,大家在写完自己的后,不妨也去测试一下,检验自己的是否符合规范。 本文同时也发布在我的github博客上,欢迎star~ 之前也手写过简单的promise,这次则是为了通过官方的Promise A+测试集,借鉴了一些下载量...

    jsummer 评论0 收藏0
  • 异步发展流程 —— Generators + co 让异步更优雅

    摘要:遍历器原有的表示集合的数据结构,主要有和,在中又加入了和,这样就有了四种数据集合,还可以组合使用它们,如数组的成员是或,这样就需要一种统一的接口机制,用来处理所有不同的数据结构。 showImg(https://segmentfault.com/img/remote/1460000018998438?w=900&h=431); 阅读原文 Generators 简介 Generato...

    dingda 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<