DEV Community

Discussion on: Tips For Using Async/Await - Write Better JavaScript!

Collapse
 
stradivario profile image
Kristiqn Tachev

There is also a useful command for Promise.allSettled since with Promise.all if one promise crashes you will lose the track for all of them.

Using allSettled will give you the result even if one of them crashes. Downside is that with both approaches if you don't do some concurrency using Promise.all and Promise.allSettled will fire up many promises and will make the buffer overflow so it is not memory wise operation.

The way it needs to be is

export type SafePromiseResult<T, E = Error> = [T | null, E | null];

export const safeHandle = async <T, E = Error>(
  promise: Promise<T>,
): Promise<SafePromiseResult<T, E>> => {
  try {
    return [await promise, null];
  } catch (e) {
    return [null, e];
  }
};
Enter fullscreen mode Exit fullscreen mode
import { safeHandle } from './safe-handle';

import concurrent from 'p-limit';

interface MyEntity {
  name: string;
}

const promises: (() => Promise<SafePromiseResult<MyEntity, Error>>)[] = [];
const processRecord = async (entry: MyEntity) => {
  /* My Async logic goes here */
  return entry;
};
const entries = [{ name: 'Oh my god' }];

for (const entry of entries) {
  promises.push(() => safeHandle(processRecord(entry)));
}

const modifiedEntries: MyEntity[] = [];

for (const [entry, error] of await Promise.all(promises.map(concurrent(20)))) {
  if (error) {
    console.log('Error', error);
  } else {
    modifiedEntries.push(entry);
  }
}

console.log(modifiedEntries);
Enter fullscreen mode Exit fullscreen mode

The same can be used with allSettled for node 12

When using concurrent approach the code itself will fire only 20 promises at time.