Kartik Mistry
Kartik Mistry

Reputation: 21

Struggling to get my promises to work in an array loop

I have been struggling with this issue for a week and have researched myself close to death. I am a total newbie. I have managed to grasp the crux of promises, but I am failing to see how to include this in a loop. I have an app that is looking through an array. There is some validation of the array against a mongoose database (which is taking time to run). I am trying to push items into a new array based on some of this validation. I know the validation is working because of the console log in the loop. However my final array is not waiting for the loop to finish. Which means I need to put the loop into a promise, or well I think, but the issue is that I don't know how to resolve it. Current output is a blank array instead of the validated array. Here is my code:

//dummy data of an array - this is originally extracted from a mongoose DB and works (it's my first promise).
        const appArray = ["5f8f25d554f1e43f3089ea5d",
        "5f8f25e854f1e43f3089ea5e",
        "5f8f25f454f1e43f3089ea5f",
        "5f8f314ab92c7f406f28b83a",
        "5f8fe50a9d44694cad91a01b",
        "5f92e8a75d848870e015dff3",
        "5f92e8b35d848870e015dff4",
        "5f92e8cb5d848870e015dff5",
        "5f8fe51d9d44694cad91a01c"];

    //the second promise takes the array above and validates it against another collection on mongoose
    function myPromise2 (response){
        return new Promise((resolve, reject) => {
            let appoints = [];
                response.forEach(e => {
                    //loop through each item of the array and look against Appointment collection
                    Appointment.findById(e, function(err, foundApp){
                        //some validation supposed to happen here and then pushed into a new array
                        appoints.push(foundApp);
                        console.log(appoints);
                    })
            }) 
            //once completed supposed to resolve and return
            resolve(appoints);
        })
    };

    myPromise2(appArray).then((response) => {console.log(response)});

Upvotes: 1

Views: 66

Answers (4)

Yakir Fitousi
Yakir Fitousi

Reputation: 545

here is my suggestion:

 const appArray = [
              "5f8f25d554f1e43f3089ea5d",
              "5f8f25e854f1e43f3089ea5e",
              "5f8f25f454f1e43f3089ea5f",
              "5f8f314ab92c7f406f28b83a",
              "5f8fe50a9d44694cad91a01b",
              "5f92e8a75d848870e015dff3",
              "5f92e8b35d848870e015dff4",
              "5f92e8cb5d848870e015dff5",
              "5f8fe51d9d44694cad91a01c"
             ];
                
 function myPromise2 (response){
     return Promise.all(response.map(id) => {
        return Appointment.findById(id).exec();
        })
     };
                
 myPromise2(appArray)
  .then(console.log) // response array
  .catch(// handle errors)
 // you can also async/await the calling part

you can also use one of:

  1. Promise.allSettled
  2. Prmoise.any (es2021)
  3. Promise.race

it's just depends on how you would like to handle the responses/failures.

Upvotes: 0

trincot
trincot

Reputation: 350272

Points to address:

  • Use the promise that mongoose provides through the .exec() method. This way you don't need new Promise
  • Collect these individual promises in an array (use .map instead of .forEach), and pass this array to Promise.all

If you do this, the code for myPromise2 reduces to the following:

function myPromise2 (response){
    return Promise.all(response.map(e => Appointment.findById(e).exec()));
}

Upvotes: 0

SeanGynane
SeanGynane

Reputation: 19

A good alternative to consider maybe Async/Await and have a look Async_await. This will hopefully answer all your issues

It's probably a good idea to look into how the JS event loop system works guide here,

Upvotes: -1

Alinex
Alinex

Reputation: 979

Here is an example which should work. Add a promise for each element to the array and then resolve the outer function if all promises have resolved.

// dummy data of an array - this is originally extracted from a mongoose DB and works (it's my first promise).
const appArray = ["5f8f25d554f1e43f3089ea5d",
"5f8f25e854f1e43f3089ea5e",
"5f8f25f454f1e43f3089ea5f",
"5f8f314ab92c7f406f28b83a",
"5f8fe50a9d44694cad91a01b",
"5f92e8a75d848870e015dff3",
"5f92e8b35d848870e015dff4",
"5f92e8cb5d848870e015dff5",
"5f8fe51d9d44694cad91a01c"];

// the second promise takes the array above and validates it against another collection on mongoose
function myPromise2 (response) {
  let appoints = [];
  response.forEach(e => {
    appoints.push(new Promise((resolve) => {
      //loop through each item of the array and look against Appointment collection
      Appointment.findById(e, function(err, foundApp) {
        //some validation supposed to happen here and then pushed into a new array
        resolve(foundApp);
      })
    }))
  })
  return Promise.all(appoints)
};

myPromise2(appArray).then((response) => {console.log(response)});

Upvotes: 2

Related Questions