Managing Concurrent Asynchronous Operations with JavaScript Promise Combinators

Promise.all

Promise.all aggregates a iterable of promises into a single promise that resolves only when every input promise fulfills. If any input promise rejects, the aggregaet promise immediately rejects with that specific reason. The resulting array strictly preserves the order of the input iterable, independent of individual resolution timing.

const createTask = (id, duration, shouldFail = false) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      shouldFail ? reject(`Error_${id}`) : resolve(`Result_${id}`);
    }, duration);
  });
};

const taskAlpha = createTask('A', 500);
const taskBeta = createTask('B', 200);
const taskGamma = createTask('C', 300, true);

Promise.all([taskAlpha, taskBeta])
  .then(values => console.log(values)) // ['Result_A', 'Result_B']
  .catch(err => console.error(err));

Promise.all([taskAlpha, taskGamma, taskBeta])
  .then(values => console.log(values))
  .catch(err => console.error(err)); // 'Error_C'

Maintaining input order is particularly valuable when executing parallel network requests where the response data must be mapped back to specific UI components or data models.

Promise.race

Promise.race returns a promise that fulfills or rejects as soon as the first promise in the provided iterable settles. The returned promise adopts the state and value/reason of that winning promise.

const quickResolve = createTask('Fast', 100);
const slowResolve = createTask('Slow', 400);
const quickReject = createTask('FailFast', 150, true);

Promise.race([slowResolve, quickResolve])
  .then(val => console.log(val)) // 'Result_Fast'
  .catch(err => console.error(err));

Promise.race([slowResolve, quickReject, quickResolve])
  .then(val => console.log(val))
  .catch(err => console.error(err)); // 'Error_FailFast'

Since execution order is non-deterministic and depends solely on completion time, this method is frequently used to implement request timeouts or to select the fastest response from redundant data sources.

Promise.allSettled

Promise.allSettled waits for all provided promises to settle, regardless of whether they fulfill or reject. It resolves to an array of objects, each desrcibing the outcome of the corresponding promise. Every object contains a status field ("fulfilled" or "rejected"), accompanied by a value property for successes or a reason property for failures.

const uploadOne = createTask('Img1', 300);
const uploadTwo = createTask('Img2', 100, true);
const uploadThree = createTask('Img3', 200);

Promise.allSettled([uploadOne, uploadTwo, uploadThree]).then(report => {
  report.forEach((entry, index) => {
    if (entry.status === 'fulfilled') {
      console.log(`Item ${index} completed: ${entry.value}`);
    } else {
      console.warn(`Item ${index} failed: ${entry.reason}`);
    }
  });
});

The output array aligns exactly with the input sequence. This combinator is ideal for batch operations where individual failures should not abort the entire workflow, such as processing multiple file uploads or aggregating independent analytics events.

Tags: javascript Promises Asynchronous Programming web development

Posted on Sat, 27 Jun 2026 16:52:29 +0000 by scription