Blog

Blog

PHODAL

NodeJS Multiple Callback解决之使用Q Promises

在上一篇《Javascript Promises模式——相当酷的Callback Hell终结者》 我们介绍了Javascript的Promise模式,接着我们就把Javascript Promise用到我们的代码中。

JavaScript Promise库 Q

之前试着用过Q,但是没有成功。或者说,在那时候不需要用上Q,所以没有深究。现在抱着学习的态度,重新试了一下,效果还不错。

A tool for making and composing asynchronous promises in JavaScript

Q是一个提供制作和创作异步Promise的JavaScript工具。Q 提供了一些辅助函数,可以将Node和其他环境适配为promise可用的。

JavaScript Promise库 Q示例

官网给了一个简单的转换的例子

step1(function (value1) {
    step2(value1, function(value2) {
        step3(value2, function(value3) {
            step4(value3, function(value4) {
                // Do something with value4
            });
        });
    });
});

将他转换为

Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
    // Do something with value4
})
.catch(function (error) {
    // Handle any error from all above steps
})
.done();

但是,我们没有看懂,我们到底做了些什么。。

JavaScript Promise 库 Q实战

原生的代码是这样子的,用的是async库

async.parallel([
    function () {
        'use strict';
        pr.get(domain, next);
    },

    function () {
        'use strict';
        gs.get(name, next);
    },

    function () {
        'use strict';
        csdn.get(name, next);
    },

    function () {
        'use strict';
        zhihu.get(name, next);
    },

    function () {
        'use strict';
        alexa.get(domain, next);
    }
]);

但是总感觉写得有点乱,不过至少离开了所谓的回调大坑。

过程大致上就是当我们需要不断往我们的result里面添加东西。

于是将代码改成Promise的形式,接着就变成这样了

github.promise_get(response, name)
    .then(function (result) {
        return pr.promise_get(result, domain);
    })
    .then(function (result) {
        return csdn.promise_get(result, name);
    })
    .then(function (result) {
        return zhihu.promise_get(result, name);
    })
    .then(function (result) {
        return alexa.promise_get(result, domain);
    })
    .then(function (result) {
        callback(result);
    });

但是这样看上去写得有点不好,因为我们将过程固化在代码中,于是试着,用别的方法对其重构。

重构的第一步后就变成这样子

var info = Information.prototype;

info.pageRank_get = function(result){
    'use strict';
    return pageRank.promise_get(result, Information.prototype.domain);
};

info.alexa_get = function(result){
    'use strict';
    return alexa.promise_get(result, Information.prototype.domain);
};

info.csdn_get= function (result) {
    'use strict';
    return csdn.promise_get(result, info.name);
};

info.github_get= function (result) {
    'use strict';
    return github.promise_get(result, info.name);
};

info.zhihu_get = function (result) {
    'use strict';
    return zhihu.promise_get(result, info.name);
};

info.initVal = function (result) {
    'use strict';
    result = [];
    return result;
};

Information.prototype.get = function (callback) {
    'use strict';
    Q.fcall(info.initVal)
        .then(info.github_get)
        .then(info.csdn_get)
        .then(info.zhihu_get())
        .then(info.pageRank_get)
        .then(info.alexa_get)
        .then(function (result) {
            callback(result);
        });
};

先提出每一个方法,然后我们就可以选择我们需要用到的库。看上去比上面整洁多了,但是我们还需要下一步,以便继续。

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签