zoukankan      html  css  js  c++  java
  • Nodejs Q promise设计思路

    Nodejs Q promise库

    前言

    Q库为nodejs提供了一个基于promise的编程方式,从此避免了一层又一层的callback调用。不过Q的灵活性也给我造成了很大困扰,我可以用promise去resolve promise么,我在then里return promise可以么?因此我研究了下Q库的源代码,幸运的是,Q库提供了一份详细的设计文档,极大的方便了我们对其设计思路的理解。

    正文

    跳过一些最原始的版本,我们先看看根据promise的最基本工作方式,能想到的最简单的promise实现。

    	var defer = function () {
    	    var pending = [], value;
    	    return {
    	        resolve: function (_value) {
    	            value = _value;
    	            for (var i = 0, ii = pending.length; i < ii; i++) {
    	                var callback = pending[i];
    	                callback(value);
    	            }
    	            pending = undefined;
    	        },
    	        then: function (callback) {
    	            if (pending) {
    	                pending.push(callback);
    	            } else {
    	                callback(value);
    	            }
    	        }
    	    }
    	};
    

    在defer里存储函数,传递到then里的callback会在原defer被resolve时触发,这是最直观的promise实现方式。
    这种实现方式无法实现链接,defer.promise.then.then.then是不能实现的,另外defer.resolve只能用实值而不能用promise。

    为了能够将promise链接起来,then函数必须也return一个promise,为了能够用promise去resolve defer。q提供了一个对实值的封装。

    	var ref = function (value) {
    	    if (value && typeof value.then === "function")
    	        return value;
    	    return {
    	        then: function (callback) {
    	            callback(value);
    	        }};
    	};
    

    如果value本身为promise,就返回该promise,如果该value为实值,就返回一个已经被resolve了的promise,resolve value就是这个实值。

    	var ref = function (value) {
    	    if (value && typeof value.then === "function")
    	        return value;
    	    return {
    	        then: function (callback) {
    	            return ref(callback(value));
    	        }};
    	};
    

    这个版本将callback的返回值也封装成promise,因此then函数的返回值可以继续用then继续链接下去。不过我们还没法用promise去resolve defer,因此引出了下面这个版本。

    	var defer = function () {
        var pending = [], value;
        return {
            resolve: function (_value) {
                if (pending) {
                    value = ref(_value); // values wrapped in a promise
                    for (var i = 0, ii = pending.length; i < ii; i++) {
                        var callback = pending[i];
                        value.then(callback); // then called instead
                    }
                    pending = undefined;
                }
            },
            promise: {
                then: function (_callback) {
                    var result = defer();
                    // callback is wrapped so that its return
                    // value is captured and used to resolve the promise
                    // that "then" returns
                    var callback = function (value) {
                        result.resolve(_callback(value));
                    };
                    if (pending) {
                        pending.push(callback);
                    } else {
                        value.then(callback);
                    }
                    return result.promise;
                }
            }
        };
    };
    

    在resolve一个defer时,defer会将该value封装成一个promise。然后会将目前存储的callbacks传递到该promise的then函数中,callback函数的调用时机取决于该promise的resolve时刻了。
    注意,这里存储的callback也不是通过then函数传递进来的callback了,为了实现then的链接,存储的callback做的实际事情是调用传递进来的callback,并且用结果去resolve内部新建的一个defer,并且then函数返回该新建defer的promise。
    简而言之,then里面传递的callback函数也可以返回一个promise,之后的then链里只有在该promise被resolve时才会被调用。

    因此现在我们的q库可以写出如下的调用方式:

    	var deferA = q.defer();
        deferA.promise //promiseA
    	    .then(function(value){
    		    //func1
    		    return promise2;
    	    })
    	    .then(function(value){
    		    //func2
    		    return promise3;
    	    });
        defer.resolve(promise1);
    

    这套函数会构造出一个链条:

     deferA ->promiseA -> hidden_deferA -> call func1 -> promise2 -> hidden_defer2 -> call func2 -> promise3
    

    也就是说,每次对一个promise调用then时,它就会创建一个隐藏的defer,返回这个defer的promise,当原promise被resolve时,该defer也会被传递进去的函数生成的结果resolve。

    到这一步为止,就是q的promise的大概实现原理了。然而q为了进一步抽象和提高,做出了一个message机制,以后的文章再仔细研究。

  • 相关阅读:
    System.IO.MemoryStream.cs
    System.IO.Stream.cs
    System.Web.HttpContext.cs
    System.Text.Encoding.cs
    System.Web.HttpRuntime.cs
    System.Web.Caching.Cache.cs
    System.Diagnostics.Stopwatch.cs
    FrameBuffer
    Java实现 洛谷 P1422 小玉家的电费
    Java实现 洛谷 P1422 小玉家的电费
  • 原文地址:https://www.cnblogs.com/lkiversonlk/p/5280342.html
Copyright © 2011-2022 走看看