DEV Community

Samuel Karani
Samuel Karani

Posted on

arrays-sugar provides async versions of javascript array methods with predicate callbacks

TLDR: This article introduces the arrays-sugar library: https://github.com/samuelkarani/arrays-sugar

Why won't this work correctly in javascript?

const array = [1, 7, 3]
array.every(async (number) => number > 1) // returns true instead of false
array.filter(async (number) => number > 1) // returns [1, 7, 3] instead of ?
array.find(async (number) => number > 1) // returns 1 instead of ?
array.findIndex(async (number) => number > 1) // returns 0 instead of ?
array.some(async (number) => number > 7) // returns true instead of ?
Enter fullscreen mode Exit fullscreen mode

All these return incorrect values because the async makes the callback return a promise which always returns truthy when evaluated.

While map is happy to give you as many promises as you want:

array.map(async (number) => number * 2)
// [ Promise { 2 }, Promise { 14 }, Promise { 6 } ]
Enter fullscreen mode Exit fullscreen mode

And reduce works with both promise and async/await callbacks:

const numbers = [1, 2, 3, 4, 5];

const sum1 = await numbers.reduce((accumulator, number) => {
  return accumulator.then(value => value + number)
}, Promise.resolve(0));
// sum1 is 15

const sum2 = await numbers.reduce(async (accumulator, number) => {
  await sleep(10) // wraps setTimeout
  return (await accumulator) + number;
}, Promise.resolve(0))
// sum2 is 15
Enter fullscreen mode Exit fullscreen mode

Introducing my new library: arrays-sugar - a set of async versions of every, filter, find, findIndex, some

Build with Typescript for the Browser or Node.js

Each function has 2 or 3 versions:

The default version that is concurrent and uses Promise.allSettled internally:

// both are equivalent
   [1, 2, 3].every(async (number) => number === 2) === true
   [1, 2, 3].everyConcurrent(async (number) => number === 2) === true
Enter fullscreen mode Exit fullscreen mode

The optimized version which may not iterate the entire array and requires that the predicate throws for falsy values instead of returning false. This is available for all functions except filter which has to go through the whole array.

const result = await findOptimized(array, async (item) => {
      if (item <= 1) {
        throw new Error("error");
      }
      return true;
    });
Enter fullscreen mode Exit fullscreen mode

The serial version that iterates each item one at a time (slow) - incase this is what you want to do.

const result = await findIndexSerial(array, async (item) => {
      await sleep(100);
      return item > 1;
    });
Enter fullscreen mode Exit fullscreen mode

That's all
Thanks for reading. I welcome your input, suggestions, feedback.
Github link: https://github.com/samuelkarani/arrays-sugar
NPM link: https://www.npmjs.com/package/arrays-sugar

One more thing
You can check out the related library AI Sugar where these functions are used internally to work with AI APIs.

Top comments (0)