Javascript Promise 学习 (中)

时隔多日,对promise有了多一点点的了解。

最近用angularjs 做开发,所以研究了一下它的 $q 

功能不算很强大,算是简化版的 Q.js

参考了一下源码,不过我的等级还差很多...

作为学习,我自己又重写了一篇。

这次的比较整齐。代码也少了 .

        $q = function (asyncFn) {
            var defer = new Deferred();
            asyncFn(defer.resolve.bind(defer), defer.reject.bind(defer));
            return defer.promise;
        };
        $q.defer = function () {
            return new Deferred();
        };
        $q.reject = function (reason) {
            var defer = new Deferred();
            defer.reject(reason);
            return defer.promise;
        };
        $q.all = function (values) {            
            var defer = new Deferred();
            var finalDatas = [];
            var count = 0;
            values.forEach(function (value, i) {
                count++;
                $q.when(value, function (data) {
                    finalDatas[i] = data; //直接按index装入,不用另外排序
                    if (--count === 0) { //一个++ 一个-- 互相抵消
                        defer.resolve(finalDatas);
                    }
                }, function (reason) {
                    defer.reject(reason);
                });
            });
            return defer.promise;
        };
        $q.when = function (value, onFulfilled, onRejected, onNotify) {            
            if (value instanceof Promise) return value.then(onFulfilled, onRejected, onNotify);           
            var defer = new Deferred();
            defer.resolve(value);
            return defer.promise.then(onFulfilled, onRejected, onNotify);          
        };

        function Deferred() {
            this.promise = new Promise();
        }
        Deferred.prototype = {
            //resolve reject 几乎是一样的, notify 在调用后不会被删除
            resolve: function (data) {
                var promise = this.promise;
                //要延误执行,防止then方法还没有设置好回调,就想要resolve的情况
                setTimeout(function () {                  
                    promise.states = "fulfilled";
                    promise._processCallback(data);
                }, 0);
            },
            reject: function (reason) {
                var promise = this.promise;
                setTimeout(function () {                 
                    promise.states = "rejected";
                    promise._processCallback(reason);
                }, 0);
            },
            notify: function (data) {
                var promise = this.promise;
                setTimeout(function () {                 
                    promise.states = "notify";
                    promise._processCallback(data, true);
                }, 0);
            },
            constructor: Deferred
        }
        //主要是保存defer, 做promise连用
        function Callback(defer, onFulfilled, onRejected, onNotify) {
            this.defer = defer;
            this.onFulfilled = onFulfilled;
            this.onRejected = onRejected;
            this.onNotify = onNotify;
        }
        function Promise() {
            this.states = "pending";
            this.value = undefined;
            this.reason = undefined;
            this._callbacks = [];
        }
        Promise.prototype = {
            then: function (onFulfilled, onRejected, onNotify) {
                //把回调收集起来,如果states不是等待就马上出发
                var defer = new Deferred();
                this._callbacks.push(new Callback(defer, onFulfilled, onRejected, onNotify));
                if (this.states !== "pending") {
                    var data = (this.states === "fulfilled") ? this.value : this.reason;
                    this._processCallback(data);
                }
                return defer.promise;
            },
            "catch": function (onRejected) {
                return this.then(null, onRejected);
            },
            'finally': function (cleanup) {                
                return this.then(cleanup, cleanup);
            },
            _processCallback: function (data, is_keepCallback) {
                //这里的data不接受promise,偷懒没做。哈哈
                var promise = this;
                if (this.states === "pending") return;             
                var states = ("on-" + this.states).toCamelCase();
                var promiseCallbacks = this._callbacks;
                var length = promiseCallbacks.length;
                for (var i = 0, l = promiseCallbacks.length; i < l; i++) {                  
                    var callback = (is_keepCallback) ?  promiseCallbacks[i] : promiseCallbacks.shift();
                    var defer = callback.defer;                   
                    if (G.isFunction(callback[states])) {
                        //要做错误处理哦
                        try {
                            //调用回调,
                            var returnValue = callback[states](data);
                            //如果是promise那就乾坤大挪移把promise连连接过去
                            if (returnValue instanceof Promise) {                              
                                returnValue.then(defer.resolve.bind(defer), defer.reject.bind(defer));//这里要用bind,因为resolve内需要引用this
                            }
                            else {
                                //不是的话就到值传给下一个promise咯
                                defer.resolve(returnValue);
                            }                           
                        }
                        catch (e) {
                            defer.reject(e);
                        }
                    }
                    else {
                        //data不是函数就直接传下去
                        defer.resolve(data);
                    }
                }
            },
            constructor: Promise
        }

 

posted @ 2014-08-31 04:02  兴杰  阅读(578)  评论(0编辑  收藏  举报