Search code examples
node.jspromise

Node js promise all multiple api calls in loop


I'm new to Node js. Here I'm calling multiple api calls in Async. But I want to return promise once all calls are finished.

function getChunkBatchDetailsResponse$(id,
  baseUri,
) {
  return new Promise((resolve) => {
   
    var options = {
      'method': 'POST',
      'url': `${configJSON.apigeeBaseUrl}/batch`,
      'headers': {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${userToken}`,
      },
      body:

    };
    request(options, function (error, response) {     
     
      if (response.body) {     

        for (let i = 0; i < totalNumberOfChunks; i++) {
        
          chunksArray.push(formData.buffer.subarray(chunkStart, chunkEnd));
          chunkStart = chunkEnd;
          chunkEnd = chunkStart + chunkSize;
          if (chunkEnd > totalFileSize) {
            chunkEnd = totalFileSize;
          }
        }
        let promiseAll = [];
        for (let i = 0; i < chunksArray.length; i++) {
          let chunkNumber = i + 1;

          //return new Promise((resolve) => {
          getChunkUploadResponse$(          ).then((response) => {
           
            logMessage(
              `Upload '${id}' took ${endUploadTime - startTime}ms to complete`,
            );

          });
          // resolve('chunk file uploaded');
          //});
        }
        // Promise.all(promiseAll);
      }

      resolve(batchMessage);
    });
  });

}


function getChunkUploadResponse$(
 
) {

  return new Promise((resolve) => {
   
    request.post(
      `${configJSON.apigeeBaseUrl}/UploadChunk`,
      {
        formData: {
          file: {
            value: buffer,
            options: {
              filename: directory.name + '.zip',
            },
          },
        },
        headers: {        
          Authorization: `Bearer ${userToken}`,
        },
      },
      (err, response) => {
        logMessage('err performing batch chunk upload.');
        logMessage(JSON.stringify(err));
        logMessage('response performing batch chunk upload');
        logMessage(JSON.stringify(response));

        if (err) {

          resolve({
            id,
            directory: directory.path,
            message: err,
            code: 500,
          });
        } else if (response) {
          const statusCode = response.statusCode;
          this.batchMessage = {
            id,
            directory: directory.path,
            message: response.statusMessage,
            code: statusCode,
          };
          if (statusCode === 201) {
            try {
              this.batchMessage.batch = JSON.parse(response.body);
              logMessage('Successfully performed a batch chunk upload');
              resolve(batchMessage);
            } catch { }
          } else if (statusCode === 413) {
            resolve({
              id,
              directory: directory.path,
              message: JSON.parse(response.body),
              code: 500,
            });

          }
          else {
            let message = '';
            try {
              message = JSON.parse(response.body);
            } catch {
              message = '';
            }
            batchMessage.message = message;
            logMessage('message performing batch chunk upload.');
            logMessage(message);
          }
          resolve(batchMessage);
        }
      },
    );
  });
}

If all calls are success should return success. Should return error if one call also fails.


Solution

  • You can use Promise.all to wait for all promises to resolve.

    function getChunkBatchDetailsResponse$(id, baseUri) {
      return new Promise((resolve, reject) => {
        var options = {
          'method': 'POST',
          'url': `${configJSON.apigeeBaseUrl}/batch`,
          'headers': {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${userToken}`,
          },
          body: // Add your request body here
        };
        request(options, function (error, response) {     
          if (error) {
            reject(error); // Reject if there's an error
            return;
          }
          if (!response || !response.body) {
            reject(new Error('No response or empty body')); // Reject if no response or empty body
            return;
          }
          
          const chunksArray = [];
          const totalNumberOfChunks = /* calculate totalNumberOfChunks */;
          const chunkSize = /* calculate chunkSize */;
          let chunkStart = 0;
          let chunkEnd = chunkSize;
          const totalFileSize = /* calculate totalFileSize */;
          
      
          for (let i = 0; i < totalNumberOfChunks; i++) {
            chunksArray.push(formData.buffer.subarray(chunkStart, chunkEnd));
            chunkStart = chunkEnd;
            chunkEnd = chunkStart + chunkSize;
            if (chunkEnd > totalFileSize) {
              chunkEnd = totalFileSize;
            }
          }
          
          const promiseAll = chunksArray.map(chunk => {
            return getChunkUploadResponse$(chunk); // Call getChunkUploadResponse$ for each chunk
          });
    
          // Wait for all promises to resolve
          Promise.all(promiseAll)
            .then(() => {
              resolve(batchMessage); // Resolve with batchMessage once all uploads are successful
            })
            .catch(error => {
              reject(error); // Reject if any upload fails
            });
        });
      });
    }
    

    Hopefully I understood your question correctly and this helps. Best of luck! :)