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

How to use Q library while converting Node async functions to promises?

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

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();

谢谢

参见documentation

例如:

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

这是使用 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") 它就开始工作了。

起初,您会想要 promisify your functions. For 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);

有了这些,您可以使用 promise 样式编写 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();

如果回调金字塔对您来说确实很奇怪,请查看

但是由于您的函数实际上不依赖于其他函数的结果,因此您可以轻松地 运行 它们并行:

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