资讯专栏INFORMATION COLUMN

尝试实现一个Promise

DTeam / 525人阅读

摘要:的实现说明没有执行里的函数说明执行了里的函数说明执行里的函数过程中出现错误和执行状态时的回调函数后返回的结果都需要执行传进来的对象不能等于当前的对象回调返回的值或者的值是对象时需要等待该对象的状态变更设置当前状态的状态和值执行回调队列里的函

function resolve_promise_value(promise,value) {//PromiseA+的实现
    var then;
    /*
        ret false 说明没有执行promise._resolve里的函数
        ret true 说明执行了promise._resolve里的函数
        ret error 说明执行promise._resolve里的函数过程中出现错误
    */
    var ret = false;
    
    /*
        resolve(promise)和执行resolve状态时的回调函数后返回的结果都需要执行resolve(promise,value)
    */
    if (value === promise) {//传进来的对象不能等于当前的Promise对象
        promise.reject(new TypeError("TypeError"));
    } else if (value && value instanceof Promise){//回调返回的值或者resolve的值是Promise对象时需要等待该Promise对象的状态变更
        value.then(promise.resolve.bind(promise),promise.reject.bind(promise));
    } else if (type(value) === "Object" || type(value) === "Function") {
        try {
            then = value.then;
        } catch(getThenErr) {
            promise.reject(thenErr);
        }
        if (type(then) === "Function") {
            try {
                then.call(value,promise.resolve.bind(promise),promise.reject.bind(promise));
            } catch(callThenErr) {
                if (promise.state === "pending") {
                    promise.reject(callThenErr);
                } 
            }
        } else {
            ret = true;
            var fn;
            promise.setState("fulfilled");//设置当前Promise状态的状态和值
            promise.value = value;
            var error;
            while (fn = promise._resolve.shift()) {//执行resolve回调队列里的函数
                try {
                    if (typeof fn == "function") {
                        var result = fn(value);
                        promise.value = result;
                    } 
                } catch (err) {
                    ret || (ret = err);//记录第一个执行出错的函数的异常信息
                }
            }
        }
    }  else {
        ret = true;
        var fn;
        promise.setState("fulfilled");//设置当前Promise状态的状态和值
        promise.value = value;
        var error;
        while (fn = promise._resolve.shift()) {//执行resolve回调队列里的函数
            try {
                if (typeof fn == "function") {
                    var result = fn(value);
                    promise.value = result;
                } 
            } catch (err) {
                (ret instanceof Error) || (ret = err);
            }
        }
    }

    if (promise.next) {
        if (ret === true) {
            resolve_promise_value(promise.next,promise.value);
        }
        else if (ret instanceof Error){
            promise.next.reject(ret);    
        }
    }
    
}

function type(arg) {//判断对象类型函数
    return  Object.prototype.toString.call(arg).match(/ (w+)/)[1];
}

function Promise(fn,value,state) {
    if (!(this instanceof Promise)) {//防止不用new调用Promise函数
        return new Promise(fn);
    }
    this._resolve = [];//Promise对象的fulfilled时执行的回调队列
    this._reject = [];//Promise对象的rejected时执行的回调队列
    this.next = null;//执行下一个Promise对象
    this.value = value || null;//当前Promise对象的值
    this.state = state || "pending";//当前Promise对象的状态
    this.id = Promise.idFactory();
    /*
        new 的时候如果有函数,就执行该函数,把resolve和reject函数作为参数传进去,并且绑定对应的Promise对象
    */
    try {
      fn && fn(this.resolve.bind(this),this.reject.bind(this));
    } catch (e) {
      this.reject(e);
    }
}

Promise.prototype = {
    equal: function(promise) {//根据id判断两个Promise对象是否相等
        return promise && (type(promise.then) === "Function") && (this.id === promise.id);
    },
    resolve: function(value) {
        if(this.state !== "pending"){
            return;
        }
        setTimeout((function() {
            resolve_promise_value(this,value)
        }).bind(this),0);
        
    },
    setState: function(state) {//设置Promise对象的状态
        this.state = state;
    },
    reject: function(value) {
        if (this.state === "pending") {
            setTimeout((function() {
                this.setState("rejected");//设置Promise对象状态
                this.value = value;//记录Promise对象对应的值
                var fn;
                var error;
                if (this._reject.length === 0) {
                    if (this.next) {
                        this.next.reject(value);
                    }
                    return;
                }
                while (fn = this._reject.shift()) {//执行reject回调函数
                    try {
                        if (typeof fn == "function") {//对于回调函数队列,只需记录最后一个函数的执行结果
                            var result = fn(value);
                            this.value = result;
                        } 
                    } catch (err) {//捕获异常,保证回调队列里的函数每一个都被执行
                        error || (error = err);
                    }
                }
                if (this.next) {
                    if (error) {
                        this.next.reject(error);
                    } 
                    /*
                        执行完当前Promise对象的回调后,如果Promise链上有下一个Promise对象,继续执行,当前的Promise对象的值传进去
                        如果error为true则说明上面代码执行中有异常,把异常对象传给下一个Promise对象
                    */
                    else {
                        resolve_promise_value(this.next,result);
                    }
                }
            }).bind(this),0)
            
        }
    },
    then: function(resolve,reject) {//增加resolve和reject回调
        if (this.state != "pending") {//如果当前Promise对象已经resolve或reject则根据当前Promise对象状态异步执行传进来的resolve或reject函数
            this.state === "fulfilled" ? (resolve = resolve || function() {}) : (reject = reject || function() {});
            setTimeout(this.state === "fulfilled" ? resolve.bind(null,this.value) : reject.bind(null,this.value),0);
            return;
        }
        (type(resolve) === "Function") && this._resolve.push(resolve);//记录resolve回调
        (type(reject) === "Function") && this._reject.push(reject);
        this.next = new Promise();//返回一个新的Promise对象
        return this.next;
    },
    catch: function(reject) {//then(undefined,callback)的语法糖
        return this.then(void 0,reject);
    }
}
Promise.all = function(promiseArr) {
    if (type(promiseArr) !== "Array") {//参数需要Promise数组
        new Error("need a Array");
    }
    var count = 0;
    var result = [];//记录每个Promise的结果
    var ret = new Promise();//返回新的Promose对象
    for (var i = 0; i< promiseArr.length ;i++) {
        promiseArr[i].then((function(i) {//每个Promise fulfilled后记录结果并且判断是否全部Promise对象已经fulfilled
            return function(value) {
                result[i] = value;
                count++;
                if (count === promiseArr.length) {//全部Promise fulfilled的话就执行resovle
                    ret.resolve(result); 
                }
            }
        })(i),function(value) {
            if (ret.state === "pending") {//有一个Promise对象reject并且ret还是pending状态的话就直接返回
                ret.reject(value);
            }    
        })
    }
    return ret;
}

Promise.race = function(promiseArr) {
    if (type(promiseArr) !== "Array") {
        new Error("need a Array");
    }
    var ret = new Promise();
    for (var i = 0; i< promiseArr.length ;i++) {
        promiseArr[i].then(function(value) {
            if (ret.state === "pending") {//有一个Promise对象resolve的话就返回,并且放弃其余的Promise对象的结果
                ret.resolve(value);
            }
        },function(value) {
            if (ret.state === "pending") {//有一个Promise对象reject的话就返回,并且放弃其余的Promise对象的结果
                ret.reject(value);
            }    
        });
    }
    return ret;
}

Promise.resolve = function(arg) {
    if (arg && typeof arg.then === "function") {//参数是Promise对象的话直接返回
        return arg;
    } else {//否则用参数构造一个Promise对象
        var result = new Promise(null,arg,"fulfilled");
        //result.resolve(arg);
        return result;
    }
}

Promise.reject = function(arg) {//同resolve
    if (arg && typeof arg.then === "function") {
        return arg;
    } else {
        var result = new Promise(null,arg,"reject");
        //result.reject(arg);
        return result;
    }
}
Promise.idFactory = (function() {//id构造工厂,id用于比较是否是同一个Promise对象
    var _id = 0;
    return function() {
        return _id += 1;
    }
})();

module.exports = Promise;

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

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

相关文章

  • PHP下的异步尝试四:PHP版的Promise

    摘要:结果打印我结论或问题这里我们基础实现了一个可以用于生产环境的后续我们会接续完善这个的特有方法,比如等后续再介绍用实现的自动执行器等附录参考中文对象入门阮一峰 PHP下的异步尝试系列 如果你还不太了解PHP下的生成器和协程,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunkify自动执行器 PHP下的...

    lentoo 评论0 收藏0
  • [翻译] Async/Await 使你的代码更简洁

    摘要:取而代之,利用事件循环体系,使用了一种类似语法的工作方式一旦非阻塞的异步操作完成之后,就可以让开发者分配的回调函数被触发。第一个尝试嵌套的回调函数下面是使用嵌套的回调函数的实现方法这可能对于任何使用者来说再熟悉不过了。 写在文章前 这篇文章翻译自 ASYNC/AWAIT WILL MAKE YOUR CODE SIMPLER,这是一篇写于2017年八月的文章,并由某专栏提名为17年十大...

    hightopo 评论0 收藏0
  • Promise 对象初尝试

    摘要:说到异步操作,可能想到的是这样以的为例对于的操作来说,是一个异步的过程,通过回调函数,在得到返回的时候才会去执行操作。 showImg(https://segmentfault.com/img/bVtSd1); 浏览器支持 showImg(https://segmentfault.com/img/bVtSd8);http://caniuse.com/promises/embed/age...

    haoguo 评论0 收藏0
  • 一篇文章用ES6手撸一个Promise

    摘要:本篇文章将会尝试用简单易懂的语言描述的原理,并且用手撸一个简单的。一个后可以通过方法,指定和时的回调函数。实现实现状态机因为是一个构造函数,使用的写法,首先想到的就是有显式声明的。 说到Promise,都知道它是比回调函数更优的一种异步编程解决方案,它可以使得异步操作逻辑变得更加清晰,是解决地狱回调的一种尝试。本篇文章将会尝试用简单易懂的语言描述Promise的原理,并且用es6手撸一...

    hsluoyz 评论0 收藏0
  • 一篇文章带你尝试拿下js异步

    摘要:单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这决定了它只能是单线程,否则会带来很复杂的同步问题。小结本身是单线程的,并没有异步的特性。当异步函数执行时,回调函数会被压入这个队列。 走在前端的大道上 本篇将自己读过的相关 js异步 的文章中,对自己有启发的章节片段总结在这(会对原文进行删改),会不断丰富提炼总结更新。 概念 JS 是单线程的语言。 单线程就意味着...

    MartinDai 评论0 收藏0

发表评论

0条评论

DTeam

|高级讲师

TA的文章

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