forEachIn.ts 1009 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. export const forEachIn = async <
  2. ItemsType extends Array<unknown>,
  3. CallbackType extends (
  4. item: ItemsType[number],
  5. index: number
  6. ) => Promise<any>,
  7. CallbackReturnType = Awaited<ReturnType<CallbackType>>
  8. >(
  9. items: ItemsType,
  10. callback: CallbackType,
  11. options: {
  12. concurrency?: number;
  13. onError?: (
  14. error: any,
  15. item: ItemsType[number],
  16. index: number
  17. ) => Promise<void>;
  18. } = {}
  19. ): Promise<CallbackReturnType[]> => {
  20. const { concurrency = 10, onError } = options;
  21. const queued = items.slice();
  22. const completed: CallbackReturnType[] = [];
  23. const next = async () => {
  24. const [item] = queued.splice(0, 1);
  25. if (typeof item === "undefined") return;
  26. const index = items.indexOf(item);
  27. try {
  28. completed[index] = await callback(item, index);
  29. } catch (error) {
  30. if (onError) await onError(error, item, index);
  31. else throw error;
  32. }
  33. await next();
  34. };
  35. await Promise.all(
  36. Array.from(Array(Math.min(items.length, concurrency)).keys()).map(next)
  37. );
  38. return completed;
  39. };