Filtering an array with a function that returns a promise

前端 未结 15 1248
遇见更好的自我
遇见更好的自我 2020-11-28 13:22

Given

let arr = [1,2,3];

function filter(num) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      if( num === 3 ) {
        res(num);
         


        
相关标签:
15条回答
  • 2020-11-28 13:52

    Here is a 2017 elegant solution using async/await :

    Very straightforward usage:

    const results = await filter(myArray, async num => {
      await doAsyncStuff()
      return num > 2
    })
    

    The helper function (copy this into your web page):

    async function filter(arr, callback) {
      const fail = Symbol()
      return (await Promise.all(arr.map(async item => (await callback(item)) ? item : fail))).filter(i=>i!==fail)
    }
    

    Demo:

    // Async IIFE
    (async function() {
      const myArray = [1, 2, 3, 4, 5]
    
      // This is exactly what you'd expect to write 
      const results = await filter(myArray, async num => {
        await doAsyncStuff()
        return num > 2
      })
    
      console.log(results)
    })()
    
    
    // Arbitrary asynchronous function
    function doAsyncStuff() {
      return Promise.resolve()
    }
    
    
    // The helper function
    async function filter(arr, callback) {
      const fail = Symbol()
      return (await Promise.all(arr.map(async item => (await callback(item)) ? item : fail))).filter(i=>i!==fail)
    }

    I'll even throw in a CodePen.

    0 讨论(0)
  • 2020-11-28 13:56

    You can do something like this...

    theArrayYouWantToFilter = await new Promise(async (resolve) => {
      const tempArray = [];
    
      theArrayYouWantToFilter.filter(async (element, index) => {
        const someAsyncValue = await someAsyncFunction();
    
        if (someAsyncValue) {
          tempArray.push(someAsyncValue);
        }
    
        if (index === theArrayYouWantToFilter.length - 1) {
          resolve(tempArray);
        }
      });
    });
    

    Wrapped within an async function...

    
    async function filter(theArrayYouWantToFilter) {
      theArrayYouWantToFilter = await new Promise(async (resolve) => {
        const tempArray = [];
    
        theArrayYouWantToFilter.filter(async (element, index) => {
          const someAsyncValue = await someAsyncFunction();
    
          if (someAsyncValue) {
            tempArray.push(someAsyncValue);
          }
    
          if (index === theArrayYouWantToFilter.length - 1) {
            resolve(tempArray);
          }
        });
      });
    
      return theArrayYouWantToFilter;
    }
    
    0 讨论(0)
  • 2020-11-28 13:59

    In case someone is interested in modern typescript solution (with fail symbol used for filtering):

    const failSymbol = Symbol();
    
    export async function filterAsync<T>(
      itemsToFilter: T[],
      filterFunction: (item: T) => Promise<boolean>,
    ): Promise<T[]> {
      const itemsOrFailFlags = await Promise.all(
        itemsToFilter.map(async (item) => {
          const hasPassed = await filterFunction(item);
    
          return hasPassed ? item : failSymbol;
        }),
      );
    
      return itemsOrFailFlags.filter(
        (itemOrFailFlag) => itemOrFailFlag !== failSymbol,
      ) as T[];
    }
    
    0 讨论(0)
提交回复
热议问题