Reputation: 1333
I have a method which accepts function as a callback parameter. Both outer method and callback function returns promises which I collect to array, waiting for them to be resolved with Q.all.
function eval() {
var colReadPromisses = [];
config.mongodb.colls.forEach(function (collName) {
var outer = mongo.readCollection(collName,
function (jsonData) {
var prom = es.pushItemToES(jsonData, esIndexName, collName, i);
colReadPromisses.push(prom);
});
colReadPromisses.push(outer);
});
return Q.all(colReadPromisses);
}
Now, inner callback method is called many times and it takes some time to process all of them. While they are being processed, promises returned from 'readCollection' method gets 'undefined' causing 'Q.all(colReadPromisses);' to resolve.
So my two questions would be why nodejs loses track to the promises returned from 'readCollection' method and how do I avoid this?
Thanks for responses!
Upvotes: 0
Views: 103
Reputation: 1
I'm assuming you want to get the results of all both readCollection and pushItemToES in the returned promise
function eval() {
return Q.all(config.mongodb.colls.map(function (collName) {
var pushPromisses = [mongo.readCollection(collName, function (jsonData) {
pushPromisses.push(es.pushItemToES(jsonData, esIndexName, collName, i));
})];
return pushPromisses[0] // once the outer promise resolves
.then(function() {
return Q.all(pushPromisses); // wait for them all (including the outer)
});
}));
}
The returned promise when resolved, will resolve to a two-dimension array
[0][0]
will be the result of the mongo.readCollection(colls[0])
[0][1..n]
will be the results of each pushItemToES
from readCollection(colls[0])
[1][0] will be the result of the
mongo.readCollection(colls[1])`[1][1..n]
will be the results of each pushItemToES
from readCollection(colls[1])
and so on
if you don't need the result of mongo.readCollection
in the returned promise
function eval() {
return Q.all(config.mongodb.colls.map(function (collName) {
var pushPromisses = [];
return mongo.readCollection(collName, function (jsonData) {
pushPromisses.push(es.pushItemToES(jsonData, esIndexName, collName, i));
}).then(function() {
return Q.all(pushPromisses);
});
}));
}
in this case the returned promise is still two dimensional, but with just the results of the pushItemToES
[0][0..n]
will be the results of each pushItemToES
from readCollection(colls[0])
[1][0..n]
will be the results of each pushItemToES
from readCollection(colls[1])
I can't see any way around the two dimensional array in the resolved promise - because the es.pushItemToES
is not called a "known" (at least not ahead of time) number of times
Upvotes: 1
Reputation: 4738
You must reorganize your code:
function eval() {
// replace forEach with map
var colReadPromisses = config.mongodb.colls.map(function (collName) {
// return pushItemToES promises
return new Promise(function(resolve) {
mongo.readCollection(collName,
function (jsonData) {
resolve(es.pushItemToES(jsonData, esIndexName, collName, i));
});
});
});
// colReadPromisses stores array of pushItemToES promises
return Q.all(colReadPromisses);
}
Upvotes: 0