javascriptarraysfilterasync-await

How to use Array.prototype.filter with async?


Background

I am trying to filter an array of objects. Before I filter, I need to convert them to some format, and this operation is asynchronous.

 const convert = () => new Promise( resolve => {
     setTimeout( resolve, 1000 );
 });

So, my first try was to do something like the following using async/await:

const objs = [ { id: 1, data: "hello" }, { id: 2, data: "world"} ];

objs.filter( async ( obj ) => {
    await convert();
    return obj.data === "hello";
});

Now, as some of you may know, Array.protoype.filter is a function which callback must return either true or false. filter is synchronous. In the previous example, I am returning none of them, I return a Promise ( all async functions are Promises ).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

So as one can assume, the code before doesn't really work... That assumption is correct.

Problem

To make filter work with an async function, I checked stackoverflow and found this topic:

Filtering an array with a function that returns a promise

Unfortunately, the chosen answer is overly complex and uses classes. This won't do for me. I am instead looking for a more simple solution, using simple functions with a functional approach.

There is one solution at the very end, using a map with a callback to simulate a filter:

https://stackoverflow.com/a/46842181/1337392

But I was hoping to fix my filter function, not to replace it.

Questions


Solution

  • There is no way to use filter with an async function (at least that I know of). The simplest way that you have to use filter with a collection of promises is to use Promise.all and then apply the function to your collection of results. It would look something like this:

    const results = await Promise.all(your_promises)
    const filtered_results = results.filter(res => //do your filtering here)
    

    Hope it helps.