Executing function when chain of promises resolves - node.js

I have written code using Q.reduce mechanism where function insertItemIntoDatabase(item) returns resolved promises.
items.reduce(function(soFar,item)
{
return soFar.then(function()
{
return insertItemIntoDatabase(item);
});
},Q());
Is there any possibilty to wait till chain is finished and then execute another function or I should chain those functions in some other way.
Thanks for help in advance

.reduce() will return the final value from the .reduce() loop, which in your case is a final promise. To execute something after the .reduce() chain and all its async operations are done, you just put a .then() handler on that final promise that is returned:
items.reduce(function(soFar,item) {
return soFar.then(function() {
return insertItemIntoDatabase(item);
});
},Q()).then(someOtherFunction);

The purpose of this pattern is exactly that: to return a promise for the result of the sequence. Written out (without reduce), it's exactly equivalent to the expression
Q()
.then(function() { return insertItemIntoDatabase(items[0]); })
.then(function() { return insertItemIntoDatabase(items[1]); })
.then(function() { return insertItemIntoDatabase(items[2]); })
…
You can simple add another .then() on it that will call your callbacks at the end of the chain.

Related

Promise chain not executing in expected order - nodejs

I have a chain of 4 promises, and 1 function at the end. The final function is executing before the previous promises in the chain have resolved.
Can someone explain to me why this might be happening?
Here is the promise chain:
updateGdax(db)
.then(updateBitstamp(db))
.then(updateBitfinex(db))
.then(updatePoloniex(db))
.then(coinMarketData.updateCoinMarketData(db))
.then(addRates(db)); //this function is executing after the first promise in the chain.
I would like each function to execute after the one listed before it, so addRates(db) should be executed last.
I can post the code from the promise functions if needed for further analyses, but I really just want to understand WHY this would happen, as my understanding is that functions in a promise chain won't execute unless the previous promise in the chain has resolved.
Unless those update functions in the then calls are partially applied (unless they return a function), they are being executed before the then is called. You need to wrap them in an anonymous function to have them executed in order. Do what the other answer says or use fat arrows:
updateGdax(db)
.then(()=>updateBitstamp(db))
.then(()=>updateBitfinex(db))
.then(()=>updatePoloniex(db))
.then(()=>coinMarketData.updateCoinMarketData(db))
.then(()=>addRates(db));
If your update functions could be rewritten to return the db after completing, then you could rewrite the calls like so, point free style:
updateGdax(db)
.then(updateBitstamp)
.then(updateBitfinex)
.then(updatePoloniex)
.then(coinMarketData.updateCoinMarketData)
.then(addRates);
Each function, would then look something like this:
function updateGdax(db) {
return db.doSomething().then(()=> db)
}
Follow that pattern, and you have yourself some nice looking javascript.
And have a look at the new async/await, included in nodejs 8. It is much more intuitive:
async function main() {
await updateGdax(db)
await updateBitstamp(db)
await updateBitfinex(db)
await updatePoloniex(db)
await coinMarketData.updateCoinMarketData(db)
await addRates(db)
}
main().catch(e => console.error(e))
Try below approach,
updateGdax(db)
.then(function(){
return updateBitstamp(db)
}).then(function (){
return updateBitfinex(db);
}).then(function() {
return updatePoloniex(db);
}).then(function(){
return coinMarketData.updateCoinMarketData(db)
}).then(function(){
return addRates(db);
}).catch(function(err){
console.log(err);
});
Hope this will work. If any of the function is returning any value and if you want to use it in subsequent function the pass that value in following function() used inside then. Refer : https://strongloop.com/strongblog/promises-in-node-js-an-alternative-to-callbacks/

Node.js - Continue promise chain for each result after promise.all()

I am using Promise.all() within a promise chain. Each promise within the Promise.all() returns a string.
The issue im having is that Promise.all() returns a Promise object to the next promise and I would like to continue the promise chain for each string.
Heres an example:
....
return Promise.all(plugins);
})
.then(function(response) {
console.log(response)
....
The response looks like:
[ 'results from p1', 'results from p2' ]
Is there any way to continue the promise chain for each of the results rather than continuing with a single object containing all results?
Promise.all expects an array of promises. So plugins is an array of promises and all the more: plugin is a Promise.
So you can just chain your plugin Promise.
This would thus become
Promise.all(plugins.map(function(plugin){
return plugin.then(function(yourPluginString){
return 'example '+ yourPluginString;
})
}))
Promise.all(), by its design returns a single promise who's resolved value is an array of resolved values for all the promises you passed it. That's what it does. If that isn't what you want, then perhaps you are using the wrong tool. You can process the individual results in a number of ways:
First, you can just loop over the array of returned results and do whatever you want to with them for further processing.
Promise.all(plugins).then(function(results) {
return results.map(function(item) {
// can return either a value or another promise here
return ....
});
}).then(function(processedResults) {
// process final results array here
})
Second, you could attach a .then() handler to each individual promise BEFORE you pass it to Promise.all().
// return new array of promises that has done further processing
// before passing to Promise.all()
var array = plugins.map(function(p) {
return p.then(function(result) {
// do further processing on the individual result here
// return something (could even be another promise)
return xxx;
});
})
Promise.all(array).then(function(results) {
// process final results array here
});
Or, third if you don't really care when all the results are done and you just want to process each one individually, then don't use Promise.all() at all. Just attach a .then() handler to each individual promise and process each result as it happens.
You can use a tool like https://github.com/Raising/PromiseChain
and implement what you say as
//sc = internalScope
var sc = {};
new PromiseChain(sc)
.continueAll([plugin1,plugin2,plugin3],function(sc,plugin){
return plugin(); // I asume this return a promise
},"pluginsResults")
.continueAll(sc.pluginsResults,function(sc,pluginResult){
return handlePluginResults(pluginResult);
},"operationsResults")
.end();
I didnt test the code if you have any problem PM me

Calling Q Promise on the basis of conditional logic

Below is my condition
if abc is true
call async func1, func2
else
call async func1
function test(): Q.Promise<boolean> {
if(abc)
Q.all([func1,func2])
else
Q.all([func1])
//if failed throw reject reason all the way in the chain
}
As shown, it can be done using if and else clause, is there a better way to call promise conditionally?
How to throw back error from any one of the promises?
I would put promises in array and append new one depending on condition:
function test(): Q.Promise<Boolean[]> {
const promises = [func1()]
if (abc) promises.push(func2())
return Q.all(promises)
}
I corrected type signature a little, because Q.all resolves with array of values (Boolean in your case) from each underlying promises. You also need to call func1 and func2. And finally, don't forget to return from test function.
You are actually pretty close already:
function test() {
if(abc)
return Q.all([func1(),func2()])
else
return func1();
}
test().then(() => {
// do whatever
}).catch(err => console.log(err));
Make sure you always return the promises as they don't get chained otherwise.

Wrapping promise in async/await

I'm struggling a bit with async/await and returning a value from a Promise.
function test () {
return new Promise((resolve, reject) => {
resolve('Hello')
})
}
async function c() {
await test()
}
As I understood things I should be able to get a value by doing:
console.log(c())
But clearly I am missing a point here as this returns a promise. Shouldn't it print "hello"? On a similar note I am unclear as to whether a callback needs to be converted to a promise before wrapping it in async/await?
I am missing a point here as this returns a promise. Shouldn't console.log(c()) print "hello"?
No, async functions always return promises. They're not magically running asynchronous code synchronously - rather the reverse, they turn synchronous-looking code (albeit speckled with await keywords) into asynchronously running one.
You can get the result value inside the asynchronous function:
async function c() {
const result = await test()
console.log(result);
return 'World';
}
c().then(console.log);
I am unclear as to whether a callback needs to be converted to a promise before wrapping it in async/await?
Yes, you can await only promises. See How do I convert an existing callback API to promises? for how to do the conversion.
Async functions return a Promise. If the function throws an error, the
Promise will be rejected. If the function returns a value, the Promise
will be resolved.

ES6 Promises - Calling synchronous functions within promise chain

I'm currently experimenting with promises and have a really basic question!
Within a promise chain, would it be bad practice to call a synchronous function? For example:
.then(function(results) {
if(checkIfResultInMemory(results) === true){
return getTotalFromMemory()
}
return results;
})
Or should my sync functions be refactored to return promises also?
Within a promise chain, would it be bad practice to call a synchronous
function?
No, it is not a bad practice at all. It is one of many expected and useful practices.
You are perfectly free to call either synchronous functions within the promise chain (from within .then() handlers) or asynchronous functions that then return a new promise.
When you return something from a .then() handler, you can return either a value (which becomes the resolved value of the parent promise) or you can return another promise (which chains onto the previous promise) or you can throw which works like returning a rejected promise (the promise chain becomes rejected).
So, that means you can call a synchronous function and get a value from it or call an async function and get another promise and then return either from the .then() handler.
All of these synchronous things are perfectly legal and each have their own objective. Here are some synchronous happenings in the .then() handler:
// modify resolved value
someAsync().then(function(val) {
return val + 12;
});
// modify resolved value by calling some synchronous function to process it
someAsync().then(function(val) {
return someSynchronousFunction(val);
});
// synchronously check the value and throw to change the promise chain
// to rejected
someAsync().then(function(val) {
if (val < 0) {
throw new Error("value can't be less than zero");
}
return val;
});
// synchronously check the value and return a rejected promise
// to change the promise chain to rejected
someAsync().then(function(val) {
if (val < 0) {
return Promise.reject("value can't be less than zero");
}
return val;
});
Here's a little example of an async operation that returns a promise followed by three synchronous .then() handlers and then outputting the final value:
function delay(t, val) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(val);
}, t);
});
}
function increment5(val) {
return val + 5;
}
delay(500, 10).then(increment5).then(function(val) {
return val - 3;
}).then(function(final) {
document.write(final);
});
Note: You only generally only want to use promises when you have or may have asynchronous operations because if everything is synchronous, then pure synchronous code is both faster to execute and easier to write. But, if you already have at least one async operation, you can certainly mix synchronous operations with that async operation and use promises to help structure the code.
A then callback function should:
return another promise
return a synchronous value (or undefined)
throw a synchronous error

Resources