I DON'T GET PROMISES

This is a placeholder post to get help on the next time I have someone to ask. Hopefully soon there will be an answer at the bottom of this post in my own words, and I will understand it!

Addition 3 months later: this article gives a pretty clear-to-understand explanation of promises.

I. DON’T. GET. THIS!!!

I have been trying to make a function work. It contained a forEach loop, and within each loop there would be a database lookup which returns a Promise.

const filterAndReformatEpisodes = async (oldSeasons, newSeasons) => {
const apiSeasonsArray = newSeasons.data.Events;
let newEpisodes = [];

oldSeasons.forEach(async (oldSeason) => {
let apiMatch = apiSeasonsArray.find(apiSeason => apiSeason.EventId === oldSeason.api_id);
if (!apiMatch) return;

let hasApiEpisode = (oldSeason.Episodes.find(prod => prod.api_id === apiMatch.EventId)) ? true : false;

if (oldSeason.Episodes.length === 0 || !hasApiEpisode) {
let director = await db.Director.findOne({ where: { api_id: apiMatch.directorId } });
let newEpisode = transform.apiEpisode(apiMatch, oldSeason, director.director_id);

newEpisodes.push(newEpisode);
}
});

console.log(`******NEW EPISODES ARRAY:`);
console.log(newEpisodes);
return newEpisodes;
};

However I never got a value out of this function—the server logs would show that the empty newEpisodes array would print and return before any of the database queries:

AXIOS GET: https://api.tvseriesapi.com/Events
RESPONSE:
{ timestamp: 'Thu, 08 Aug 2019 21:16:30 GMT',
status: 200,
statusText: 'OK' }
******NEW EPISODES ARRAY:
[]
Executing: SELECT "director_id", "api_id" FROM "Directors" WHERE "Director"."api_id" = 150 LIMIT 1;
Executing: SELECT "director_id", "api_id" FROM "Directors" WHERE "Director"."api_id" = 17 LIMIT 1;
Executing: SELECT "director_id", "api_id" FROM "Directors" WHERE "Director"."api_id" = 32 LIMIT 1;
Executing: SELECT "director_id", "api_id" FROM "Directors" WHERE "Director"."api_id" = 19 LIMIT 1;
...

I tried a lot of things to get this to work. Finally one StackOverflow answer said I have to use Array.map() instead of Array.forEach() (…well more like 7-8 said it, but this was the first one I could get to work!…) to ensure the promises all resolve before returning the newEpisodes array:

const filterAndReformatEpisodes = async (oldSeasons, newSeasons) => {
const apiSeasonsArray = newSeasons.data.Events;
let newEpisodes = [];

await Promise.all(oldSeasons.map(async (oldSeason) => {
let apiMatch = apiSeasonsArray.find(apiSeason => apiSeason.EventId === oldSeason.api_id);
if (!apiMatch) return;

let hasApiEpisode = (oldSeason.Episodes.find(prod => prod.api_id === apiMatch.EventId)) ? true : false;

if (oldSeason.Episodes.length === 0 || !hasApiEpisode) {
let director = await db.Director.findOne({ where: { api_id: apiMatch.directorId } });
let newEpisode = transform.apiEpisode(apiMatch, oldSeason, director.director_id);

newEpisodes.push(newEpisode);
}
}));

return newEpisodes;
};

This had the desired outcome.

WHY!? 🧐