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