美文网首页
Nodejs Q promise实现初探

Nodejs Q promise实现初探

作者: 泡沫与周期_白羊Jerry | 来源:发表于2016-08-08 09:58 被阅读441次

前言

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机制,以后的文章再仔细研究。

相关文章

  • Nodejs Q promise实现初探

    前言 Q库为nodejs提供了一个基于promise的编程方式,从此避免了一层又一层的callback调用。不过Q...

  • nodejs + cheerio + Promise(blueb

    文章概要 使用nodejs + cheerio + Promise(bluebird库实现)的nodejs课程数据...

  • 纯手写实现自己的nodejs promise 库

    纯手写实现自己的nodejs promise 库什么是Promise?promise 链Async/Await后续...

  • Promise async/await

    Promise async/await 参考初探promise promise 理解 JavaScript ...

  • 实现一个简单的Promise/Deferred框架

    利用nodejs的event模块,可以实现一个最简单的Promise/Deferred框架: Promise De...

  • $q

    $q服务 q服务是AngularJS中自己封装实现的一种Promise实现,相对与Kris Kwal's Q要轻量...

  • 使用angular和构建工具来搭建框架,开发项目

    内置组件包括{ $q服务:实现promise功能 $http:处理ajax请求 ng-repeat ng-mode...

  • 初探Promise

    摘自:阮一峰 http://es6.ruanyifeng.com/#docs/promise 一、首先,我们要弄明...

  • Promise初探

    遭遇“恶魔金字塔” 项目需要,封装了一个省市区的地址选择器组件。 可以根据省份id、城市id和区id对组件设置默认...

  • Promise初探

    1. promise有什么用 promise提供了对js异步编程的新的解决方案。 他改变了传统回调的位置,不用去思...

网友评论

      本文标题:Nodejs Q promise实现初探

      本文链接:https://www.haomeiwen.com/subject/utxrsttx.html