node.jsmeteorasync-awaitnode-request

Node Js get request in for loop and collect responses in an object


nodejs / meteorjs newbie here, I am trying to query an api in for loop and collect all responses in one object and return that object. here is my code set up


const req = require('request');

const getallJira = (namespace, services) => {

  let allJiraResponses = {};

  for (let i in services) {
    let _serviceName = services[i];
    const options = {
      method: 'POST',
      url: 'https://jira/jira/rest/api/2/search',
      headers: {
        'Content-Type': 'application/json',
        Authorization: base64Auth,
        Accept: 'application/json',
      },
      body: JSON.stringify({
        jql: `NAMESPACE = ${namespace} AND labels = 'kind/promotion' AND (SERVICE_NAME =  '${_serviceName}' OR 'Service Name/Package Name' = '${_serviceName}')`,
        maxResults: 1000000,
        startAt: 0,
        fields,
      }),
    };

    request(options, function(error, response) {
      if (error) throw new Error(error);
      const jiraResponse = JSON.parse(response.body);
      allJiraResponses[_serviceName] = jiraResponse;
    });
  }

  return allJiraResponses;
};

however the final allJiraResponses is returned empty because of the asynchronous nature of request. How do i record all the responses from jira API in the object and return it to the caller of getallJira


Solution

  • I think you should separate into function to make it clearer

    the first one to get the result for a single service

    const  getJiraService = ( namespace, serviceName) => new Promise((resolve, reject) => {
       const options = {
          method: 'POST',
          url: 'https://jira/jira/rest/api/2/search',
          headers: {
            'Content-Type': 'application/json',
            Authorization: base64Auth,
            Accept: 'application/json',
          },
          body: JSON.stringify({
            jql: `NAMESPACE = ${namespace} AND labels = 'kind/promotion' AND (SERVICE_NAME =  '${serviceName}' OR 'Service Name/Package Name' = '${serviceName}')`,
            maxResults: 1000000,
            startAt: 0,
            fields,
          }),
        };
    
        request(options, function(error, response) {
          if (error) {
            resolve({serviceName, error});
            return;
          }
          const jiraResponse = JSON.parse(response.body);
          resolve({serviceName, jiraResponse})
        });
    
    })
    
    const getallJira =  async (namespace, services) => {
    const results = await Promise.all(services.map(s => getJiraService(namespace, s));
    return results.reduce((res, {serviceName, error, jiraResponse}) => {
      if(!!jiraResponse){
        return {
          ...res,
          serviceName:  jiraResponse
        };
      }
      return res;
    
    }, {})