21. What are Promise.all and Promise.race methods in JavaScript? When would you prefer to use one over the other?
medium
In JavaScript, the `Promise.all()` and `Promise.race()` methods are both used to handle multiple promises, but they serve different purposes and should be used depending on the specific use case.

Promise.all() method:

The `Promise.all()` method takes an array of promises as an argument and returns a new promise that resolves when all of the input promises have resolved or rejected, whichever comes first. It is useful when we need to execute code after all of the input promises have completed their execution, regardless of whether they resolved or rejected.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 fulfilled');
  }, 2000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('Promise 2 failed');
  }, 3000);
});

const promises = [promise1, promise2];

Promise.all(promises).then(results => {
  console.log(results); // logs ['Promise 1 fulfilled', 'Promise 2 failed']
});

In this example, we create two promises that resolve after different time intervals. We then use the `Promise.all()` method to handle both promises and log their resolved values to the console. Since promise 2 rejects before promise 1 resolves, the `Promise.all()` method returns immediately with the rejected value of promise 2.

Promise.race() method:

The `Promise.race()` method takes an array of promises as an argument and returns a new promise that resolves or rejects as soon as one of the input promises does so, whichever comes first. It is useful when we need to execute code as soon as one of the input promises completes their execution, regardless of whether they resolved or rejected.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 fulfilled');
  }, 2000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('Promise 2 failed');
  }, 3000);
});

const promises = [promise1, promise2];

Promise.race(promises).then(results => {
  console.log(results); // logs 'Promise 1 fulfilled'
});

In this example, we create two promises that resolve after different time intervals. We then use the `Promise.race()` method to handle both promises and log their resolved value to the console. Since promise 1 resolves before promise 2 rejects, the `Promise.race()` method returns immediately with the resolved value of promise 1.


In summary, we should use Promise.all() when we need to execute code after all input promises have completed their execution, regardless of whether they resolved or rejected, and we should use Promise.race() when we need to execute code as soon as one input promise completes its execution, regardless of whether it resolved or rejected.