Reputation: 451
I am trying to iterate through a range of dates to return the top song for each date. So I have a for loop. Within this for loop a function is called to look through my database for the top song. Therefore I wrapped it in a promise in order that it would hold up the for loop, but this approach does not seem to work either. Can someone explain a better approach to solve this issue.
app.post('/getDate', function (req, res) {
this.tracks = [];
let until = new Date(req.body.dateToOutput);
for (var d = new Date(req.body.dateFromOutput); d <= until; d.setDate(d.getDate() + 1)) {
date = d.toLocaleDateString('en-US', { timeZone: 'UTC' });
console.log('date', date);
new Promise(function (resolve, reject) {
getDate(date).then(() => {
resolve();
})
});
}
console.log(this.tracks);
});
function getDate(date) {
return new Promise(function (resolve, reject) {
Track.find({ Date: date }, function (err, track) {
if (!err) {
console.log(track);
this.tracks.push(track);
resolve();
}
else {
reject();
}
}).sort({ Streams: -1 }).limit(1);
});
}
Upvotes: 0
Views: 62
Reputation: 336
I think the promise is not being executed, and also i think you are pointing to an undefined object in your getDate function, and the for loop doesn't waits to a promise to be solved or rejected. see this:
new Promise(function (resolve, reject) {
getDate(date).then(() => {
resolve();
})
});
you are creating a new promise but you never execute this promise.
also in the function getDate
you are pointing to an object that doesn't exists in his context:
this.tracks.push(track);
This will throw you some errors, because this.tracks
is not part of getDate
function is part of an anonymous function which is called by the app.post
method.
so instead of pushing something in this.tracks
directly, you must return the track itself:
if (!err) {
console.log(track);
resolve(track);
}
then you should use async - await to obligate the loop for make a pause at the promise until this being resolved or rejected, so your anonymous function, should be now an async anonymous function in order to use await, also you don't need a wrapper of a promise inside another promise, i mean you don't need this:
new Promise(function (resolve, reject) {
getDate(date).then(() => {
resolve();
})
});
You only need this:
getDate(date).then(() => {
resolve();
})
because the getDate() function returns a promise itself.
So this is how your code looks after making all these changes:
const response = app.post('/getDate', async function (req, res) {
this.tracks = [];
let until = new Date(req.body.dateToOutput);
for (var d = new Date(req.body.dateFromOutput); d <= until; d.setDate(d.getDate() + 1)) {
date = d.toLocaleDateString('en-US', { timeZone: 'UTC' });
console.log('date', date);
const ctrack = await getDate(date);
this.tracks.push(ctrack);
}
console.log(this.tracks);
return this.tracks;
});
function getDate(date) {
return new Promise(function (resolve, reject) {
Track.find({ Date: date }, function (err, track) {
if (!err) {
console.log(track);
resolve(track);
}
else {
reject();
}
}).sort({ Streams: -1 }).limit(1);
});
}
And now that you have the response as a promise, because an async function returns a promise... you can then and catch it and use the response:
response.then(trackList =>{
console.log(trackList);
}).catch(()=>{
console.error("something went wrong...!");
})
Upvotes: 1