浅谈Javascript中Promise对象的完成

本文同步自我得博客:http://www.joeray61.com

很多做前端的朋侪应当都听说过Promise(或许Deferred)对象,本日我就讲一下我对Promise的熟悉

What?

PromiseCommonJS的范例之一,具有resolverejectdonefailthen等要领,能够协助我们掌握代码的流程,防止函数的多层嵌套。现在异步在web开辟中越来越重要,关于开辟人员来讲,这类非线性实行的编程会让开辟者以为难以掌控,而Promise能够让我们更好地掌控代码的实行流程,jQuery等盛行的js库都已完成了这个对象,岁尾行将宣布的ES6也将原生完成Promise

Why

设想如许一个场景,两个异步要求,第二个须要用到第一个要求胜利的数据,那末我们代码能够如许写

    ajax({
        url: url1,
        success: function(data) {
            ajax({
                url: url2,
                data: data,
                success: function() {
                }
            });
        }
    });

假如继续下去在回调函数中举行下一步操纵,嵌套的层数会越来越多。我们能够举行恰当的革新,把回调函数写到表面

    function A() {
        ajax({
            url: url1,
            success: function(data) {
                B(data);
            }
        });
    }
    function B(data) {
        ajax({
            url: url2,
            success: function(data) {
                ......
            }
        });
    }

即使是改写成如许,代码照样不够直观,然则假如有了Promise对象,代码就能够写得异常清楚,一览无余,请看

new Promise(A).done(B);

如许函数B就不必写在A的回调中了

How

现在的ES规范中还未支撑Promise对象,那末我们就本身着手,饱食暖衣吧。思绪大抵是如许的,用2个数组(doneListfailList)离别存储胜利时的回调函数行列和失利时的回调行列

  • state: 当前实行状况,有pendingresolvedrejected3种取值

  • done: 向doneList中增加一个胜利回调函数

  • fail: 向failList中增加一个失利回调函数

  • then: 离别向doneListfailList中增加回调函数

  • always: 增加一个不管胜利照样失利都邑挪用的回调函数

  • resolve: 将状况更改成resolved,并触发绑定的一切胜利的回调函数

  • reject: 将状况更改成rejected,并触发绑定的一切失利的回调函数

  • when: 参数是多个异步或许耽误函数,返回值是一个Promise兑现,当一切函数都实行胜利的时刻实行该对象的resolve要领,反之实行该对象的reject要领
    下面是我的详细完成历程:

var Promise = function() {
    this.doneList = [];
    this.failList = [];
    this.state = 'pending';
};

Promise.prototype = {
    constructor: 'Promise',
    resolve: function() {
        this.state = 'resolved';
        var list = this.doneList;
        for(var i = 0, len = list.length; i < len; i++) {
            list[0].call(this);
            list.shift();
        }
    },
    reject: function() {
        this.state = 'rejected';
        var list = this.failList;
        for(var i = 0, len = list.length; i < len; i++){
            list[0].call(this);
            list.shift();
        }
    },
    done: function(func) {
        if(typeof func === 'function') {
            this.doneList.push(func);
        }
        return this;
    },
    fail: function(func) {
        if(typeof func === 'function') {
            this.failList.push(func);
        }
        return this;
    },
    then: function(doneFn, failFn) {
        this.done(doneFn).fail(failFn);
        return this;
    },
    always: function(fn) {
        this.done(fn).fail(fn);
        return this;
    }
};

function when() {
    var p = new Promise();
    var success = true;
    var len = arguments.length;
    for(var i = 0; i < len; i++) {
        if(!(arguments[i] instanceof Promise)) {
            return false;
        }
        else {
            arguments[i].always(function() {
                if(this.state != 'resolved'){
                    success = false;
                }
                len--;
                if(len == 0) {
                    success ? p.resolve() : p.reject();
                }
            });
        }
    }
    return p;
}

Improve

现在只是完成了Promise的基本功用,但仍然另有没法处置惩罚的状况,例如要完成3个或3个以上的异步要求的串行,现在我的Promise没有办法支撑new Promise(A).then(B).then(C)如许的情势,jQuery在1.7的版本中为Deferred(Promise)对象完成了pipe函数,能够经由过程这个函数完成上述功用,代码为$.Deferred(A).pipe(B).then(C),我尝试去读了jQuery这部份的代码,然则没能读懂,愿望有大神能够给一些完成思绪

    原文作者:JoeRay61
    原文地址: https://segmentfault.com/a/1190000000684654
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞