Reputation: 28116
I am building up an array of promises from Mongoose's Model.save()
But for some reason the returned data from Promise.all()
is an array of undefined
Code
const saveDataArray = [];
//go through results and save them to the db
Object.keys(passData.scrapeUniqueData).map((index) => {
const result = gamesExport.addGame(passData.scrapeUniqueData[index], passData.leagueInfo.league_id, passData.leagueInfo.leagueID, passData.leagueInfo.year);
if(result)
saveDataArray.push(result);
});
//const -> saveDataArray
[Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise, Promise]
return Promise.all(saveDataArray)
.then((savedDBData) => {
console.info('savedDBData', savedDBData);
console.info('saveDataArray', saveDataArray);
passData.savedDBGames = savedDBData.filter(function(n){ return n != undefined });
return passData;
})
//const -> savedDBData
[undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
So imo savedDBData
should be returning the same as `saveDataArray. Why isn't Promise.all returning the data that was saved?
AddGame
addGame: (details, league_id, leagueID, year) => {
"use strict";
if(!details.result && details.result[0] === "P"){
console.error('result skipped for postponded match');
return;
}
if (details && details.notes !== "Postponed" && !details.postponed) {
var result = new Games();
result.fixtureID = details.fixtureID;
if (details.date.toString().indexOf('z') === -1) {
result.date = Date.parse(moment(details.date.toString(), "DD-MM-YYYY H:m").format());
} else {
result.date = details.date;
}
result.home_id = details.home_id._id;
result.away_id = details.away_id._id;
result.league_id = league_id;
result.leagueID = leagueID;
result.year = year;
result.norsemen = details.home_id.name.isNorsemen() || details.away_id.name.isNorsemen();
if (details.result) {
if (details.result.home === "A" && details.result.away === "A") {
result.result = ['A', 'A'];
result.postponed = true;
} else if (details.result.home === "H" && details.result.away === "W") {
result.result = ['H', 'W'];
} else if (details.result.home === "A" && details.result.away === "W") {
result.result = ['A', 'W'];
} else if (details.result.home === "C" && details.result.away === "C") {
result.result = ['C', 'C'];
result.cancelled = true;
} else if (details.result.home === "P" && details.result.away === "P") {
result.result = ['P', 'P'];
result.postponed = true;
} else {
result.result = [parseInt(details.result.home), parseInt(details.result.away, 10)];
}
}
return result.save(function (err, saveData) {
if (err) console.error(err);
return result;
});
} else {
return null;
}
},
Upvotes: 0
Views: 485
Reputation: 203554
When you pass a callback function to a Mongoose method, it assumes that you won't be using the promise that it returns as well.
I'm not sure if this is by design (I guess it is, because otherwise both the regular callback and the promise handler will be called, with the same result), but I can reproduce your issue with code that looks like this:
let doc = new Model(...);
doc.save((err, res) => {
console.log('CB RES', res);
}).then(res => {
console.log('PR RES', res);
});
PR RES
("promise result") is logged with a result of undefined
, but CB RES
("callback result") logs a proper document. When you don't pass a callback function to save()
, then PR RES
logs the proper document.
So you should rewrite addGame
to just return a promise, and not pass in a callback function:
return result.save().catch(function(err) {
console.error(err);
// XXX: be aware that if you don't do anything else here,
// the error will _just_ be logged, but not propagated.
// This is also what your original code does, so I assume
// it's intentional.
});
Upvotes: 1