如何在将Node异步函数转换为promises时使用Q库?

时间:2015-03-26 20:08:43

标签: javascript node.js promise q

如何在下面的代码中使用Promise?

function async_f1(callback) {
    setTimeout(function() {
        callback("Async function 1...");
    }, 1000);
}

function async_f2(callback) {
    setTimeout(function() {
        callback("Async function 2!...");
    }, 1000);
}

function async_f3(callback) {
    setTimeout(function() {
        callback("Second async function 3!...");
    }, 1000);
}

function doAll() {
    async_f1(function(result1) {
        async_f2(function(result2) {
            async_f3(function(result3) {
                console.log("Final result:", result1 + " " + result2 + " " + result3);
            })
        })
    });

}

doAll();

谢谢

3 个答案:

答案 0 :(得分:0)

请参阅documentation

例如:

var promise = Q.nfcall(someAsyncFunction, arg1, ...);

答案 1 :(得分:0)

以下是使用Q.nfcall的承诺的工作代码段:

var Q = require('q');


var a = Q.nfcall(function async_f1(callback) {
    setTimeout(function() {
        callback(null, "Async function 1...");
    }, 1000);
});

var b = Q.nfcall(function async_f2(callback) {
    setTimeout(function() {
        callback(null, "Async function 2!...");
    }, 1000);
});

var c = Q.nfcall(function async_f3(callback) {
    setTimeout(function() {
        callback(null, "Second async function 3!...");
    }, 1000);
});

function doAll() {
    Q.all([a, b, c]).then(function(result) {
        console.log(result);
    }).fail(function(err) {
        console.log(err);
    })

}

doAll();

以下是Q.denodeify版本:

var Q = require('q');


var a = function async_f1(callback) {
    setTimeout(function() {
        callback(null, "Async function 1...");
    }, 1000);
};

var b = function async_f2(callback) {
    setTimeout(function() {
        callback(null, "Async function 2!...");
    }, 1000);
};

var c = function async_f3(callback) {
    setTimeout(function() {
        callback(null, "Second async function 3!...");
    }, 1000);
};

var a_promise = Q.denodeify(a);
var b_promise = Q.denodeify(b);
var c_promise = Q.denodeify(c);

function doAll() {
    Q.all([a_promise(), b_promise(), c_promise()]).then(function(result) {
        console.log(result);
    }).fail(function(err) {
        console.log(err);
    })

}

doAll();

我之前的尝试失败了,因为我错过了一个重点:

Q.nfcall工作,您的回调必须使用 callback(error, data)模式。以前我没有添加错误参数,所以我没有得到任何错误,但没有任何输出。一旦我将其修改为callback(null, "Async function 1"),它就开始工作了。

答案 2 :(得分:0)

首先,您需要promisify your functions。对于interfacing with nodeback functions,您通常使用Q.denodeify,但您的示例函数始终会将结果传回第一个参数。所以我们需要编写自己的函数:

function promisify(fn) {
    return function() {
        var args = Array.prototype.slice.call(arguments), ctx = this;
        return Q.Promise(function(resolve) {
            fn.apply(ctx, args.concat([resolve]);
        });
    };
}

并像

一样使用它
var f1 = promisify(async_f1),
    f2 = promisify(async_f2),
    f3 = promisify(async_f3);

通过这些,您可以使用承诺风格编写doAll函数:

function doAll() {
    return f1().then(function(result1) {
        return f2().then(function(result2) {
            return f3().then(function(result3) {
                return "Final result:", result1 + " " + result2 + " " + result3;
            });
        });
    }).then(function(res) {
        console.log(res);
    });
}
doAll();

如果回调金字塔看起来很奇怪,请查看How do I access previous promise results in a .then() chain?

但是,由于您的功能实际上并不依赖于其他功能,您可以轻松地并行运行它们:

function doAll() {
    return Q.all([f1(), f2(), f3()]).then(function(result) {
        console.log("Final result:", result1 + " " + result2 + " " + result3);
    });
}