Reputation:
From the code below i am trying to resolve the promise ONLY after games object has its data filled from the api loop if that makes sense but it keeps displaying empty:
{
info: summoner,
matchIds: { << used for loop below
0: matchIds['matches'][0].matchId,
1: matchIds['matches'][1].matchId,
2: matchIds['matches'][2].matchId,
3: matchIds['matches'][3].matchId,
4: matchIds['matches'][4].matchId,
5: matchIds['matches'][5].matchId,
6: matchIds['matches'][6].matchId,
7: matchIds['matches'][7].matchId,
8: matchIds['matches'][8].matchId,
9: matchIds['matches'][9].matchId
}
}
var getMatches = function(summoner) {
var promise = new Promise(function(resolve, reject){
var opt = {};
var games = {}; << object needs to be filled
for (var val in Object.keys(summoner['matchIds'])) {
var match = summoner['matchIds'][val];
opt.id = match;
api.getMatchById(opt, function(err, game) {
games[x] = game;
})
}
console.log(games);
resolve({games});
});
return promise;
};
Upvotes: 0
Views: 182
Reputation: 503
Hello possible solution if use, not pure promises but bluebird
library
const Promise = require('bluebird');
const promise = new Promise(function (resolve, reject) {
const propsPromise = {};
Object.keys(summoner['matchIds']).forEach(val => {
const match = summoner['matchIds'][val];
propsPromise[match] = new Promise((resolve, reject) => {
api.getMatchById(opt, (err, game) => {
if (err) {
return reject(err);
}
resolve(game);
});
});});
return Promise.props(propsPromise);
});
You out promise will be solved as soon as the object will be resolved with content.
Link to documentation - Promise.props
Upvotes: 0
Reputation: 708016
Your code is assuming that api.getMatchById()
is synchronous, but it likely is not and thus the for
loop completed before any of your api.getMatchById()
calls complete, thus games is always empty when you resolve. You will have to keep track of when all the api.getMatchById()
calls are done and only resolve when that happens.
The best way to code this would be to promisify api.getMatchById()
and then use Promise.all()
to track when they are all done. If you weren't going to do that, then you could create a manual counter:
var getMatches = function(summoner) {
return new Promise(function(resolve, reject){
var cntr = 0;
var opt = {};
var games = {};
var keys = Object.keys(summoner['matchIds']);
keys.forEach(function(key) {
var match = summoner['matchIds'][key];
opt.id = match;
api.getMatchById(opt, function(err, game) {
// need some error handling here
games[x] = game;
++cntr;
// when all api calls are done, resolve
if (cntr === keys.length) {
resolve({games});
}
})
});
});
};
Also, please don't ever use for/in to iterate the items of an array as it can be prone to problems. In ES6, you can use for/of. I used .forEach()
here.
Upvotes: 0