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

How do I use Promises at the code below?

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

Thank you

See the documentation.

For example:

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

Here is working snippet with promises using 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();

Here is Q.denodeify version:

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

My previous attempts were failing because I missed an important point:

In order to Q.nfcall work, your callback must use callback(error, data) pattern. Previously I didn't add error argument so I didn't get any errors but neither any output. Once I fixed it as callback(null, "Async function 1") it started to work.

At first, you'll want to promisify your functions. For interfacing with nodeback functions you'd usually use Q.denodeify, but your example functions always pass their results back in the first argument. So we'll need to write our own function:

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]);
        });
    };
}

and use it like

var f1 = promisify(async_f1),
    f2 = promisify(async_f2),
    f3 = promisify(async_f3);

With these, you can write your doAll function using promise style:

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

If that callback pyramid does look odd to you, have a look at How do I access previous promise results in a .then() chain?.

But as your functions actually don't rely on results of the others, you could easily run them in parallel:

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