0

My NodeJS controller is sending the response before finish running the wait methods.

The response with the 'OK' message is immediately send back to the client (browser) when I run it. It sends the response before running all the methods.

try {
   const ep = await new keysModel().getKeys(); // key is a list of objects
   await ep.map( async (key) => {
      // some operations with the keys here
      // call a fetch to a third party API
      await fetch(urlRequest, {
         method: 'post',
         body:    JSON.stringify(myJSONObject),
         headers: { 
            'Authorization': `Basic ${base64.encode(`${key.APIKey}:${key.PasswordKey}`)}`,
            'Content-Type': 'application/json'
         },
      })
      .then(async res => res.json())
      .then(async json => {
         // Here I have some operations with the json response data
         // It includes some database queries
      })
      .catch(async err => {
         // await method to send me an email
         res.status(501).send('error');
      });
   });
   res.status(202).send('OK');
} catch() {
   // await method to send me an email
   res.status(501).send('error');
}

Below is the route:

const express =  require('express');
const router = express.Router();
router.get('/myPath', myController.testMethod);

I'm new with NodeJS. Trying to understand how it works.

Thanks

myTest532 myTest532
  • 2,091
  • 3
  • 35
  • 78

2 Answers2

2

I think Promise.all should work, eg. use async await with array map :)

try {
   const ep = await new keysModel().getKeys(); // key is a list of objects
   await Promise.all(ep.map(async (key) => {
      // some operations with the keys here
      // call a fetch to a third party API
      return fetch(urlRequest, {
         method: 'post',
         body:    JSON.stringify(myJSONObject),
         headers: { 
            'Authorization': `Basic ${base64.encode(`${key.APIKey}:${key.PasswordKey}`)}`,
            'Content-Type': 'application/json'
         },
      })
      .then(async res => res.json())
      .then(async json => {
         // Here I have some operations with the json response data
         // It includes some database queries
      })
      .catch(async err => {
         // await method to send me an email
         res.status(501).send('error');
      });
   }));
   res.status(202).send('OK');
} catch() {
   // await method to send me an email
   res.status(501).send('error');
}
alex-bu-89
  • 54
  • 3
2

By default, map is not async function, using async on map's call back would not be asynced. you can use one of Promise.all, Promise.allSettled, Promise.any, Promise.race (depends on your needs, please read more about Promises here.

short example for your case, i will use Promise.all for the example.

try {
    const ep = await new keysModel().getKeys(); // key is a list of objects
    Promise.all(
      ep.map((key) => {
      // some operations with the keys here
      // call a fetch to a third party API
      fetch(urlRequest, {
         method: 'post',
         body:    JSON.stringify(myJSONObject),
         headers: { 
            'Authorization': `Basic 
            ${base64.encode(`${key.APIKey}:${key.PasswordKey}`)}`,
            'Content-Type': 'application/json'
         },
      })
      .then(/* Handle array of responses */)
      .catch(/* Handle errors */);
  );
  // proceed..
  } catch() {
  // await method to send me an email
  res.status(501).send('error');
}
Yakir Fitousi
  • 537
  • 3
  • 12