How to use Array.prototype.filter with async?

前端 未结 5 1790
闹比i
闹比i 2020-12-29 01:56

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.

         


        
相关标签:
5条回答
  • 2020-12-29 02:05

    Use Scramjet fromArray/toArray methods...

    const result = await scramjet.fromArray(arr)
                                 .filter(async (item) => somePromiseReturningMethod(item))
                                 .toArray();
    

    as simple as that - here's a ready example to copy/paste:

    const scramjet = require('../../');
    
    async function myAsyncFilterFunc(data) {
        return new Promise(res => {
            process.nextTick(res.bind(null, data % 2));
        });
    }
    
    async function x() {
        const x = await scramjet.fromArray([1,2,3,4,5])
            .filter(async (item) => myAsyncFilterFunc(item))
            .toArray();
        return x;
    }
    
    x().then(
        (out) => console.log(out),
        (err) => (console.error(err), process.exit(3)) // eslint-disable-line
    );
    

    Disclamer: I am the author of scramjet. :)

    0 讨论(0)
  • 2020-12-29 02:12

    Build a parallel array to your array which you want to call filter on. Await all of the promises from your filter func, in my eg, isValid. In the callback in filter, use the 2nd arg, index, to index into your parallel array to determine if it should be filtered.

    // ===============================================
    // common
    // ===============================================
    const isValid = async (value) => value >= 0.5;
    const values = [0.2, 0.3, 0.4, 0.5, 0.6];
    
    
    // ===============================================
    // won't filter anything
    // ===============================================
    const filtered = values.filter(async v => await isValid(v));
    console.log(JSON.stringify(filtered));
    
    
    // ===============================================
    // filters
    // ===============================================
    (async () => {
      const shouldFilter = await Promise.all(values.map(isValid));
      const filtered2 = values.filter((value, index) => shouldFilter[index]);
    
      console.log(JSON.stringify(filtered2));
    })();
    

    This behavior makes sense since any Promise instance has a truthy value, but it's not intuitive at a glance.

    0 讨论(0)
  • 2020-12-29 02:12

    All i can say is that this guy Tamás Sallai explained it pretty well: Basically you do 2 functions:

    1. One that creates the conditions for an object to pass
    2. One that receives the objects and returns true or false according to conditions

    Article: https://advancedweb.hu/how-to-use-async-functions-with-array-filter-in-javascript/

    0 讨论(0)
  • 2020-12-29 02:14

    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.

    0 讨论(0)
  • 2020-12-29 02:25
        Array.prototype.asyncFilter =function( filterFn) {
           const arr = this;
           return new Promise(function(resolve){
             const booleanArr = [];
             arr.forEach(function (e) { 
                booleanArr.push(filterFn(e))
             })
             Promise.all(booleanArr).then(function (booleanArr) {
               const arr2 = arr.filter(function (e, i) {
                 return booleanArr[i]
               })
               resolve(arr2)
             })
           })
        }
    /** use it like this**/
    const arr=[1,2,3]
    arr.asyncFilter(async e=>{}).then(...)
    
    0 讨论(0)
提交回复
热议问题