使用返回promise的函数过滤数组 [英] Filtering an array with a function that returns a promise

查看:566
本文介绍了使用返回promise的函数过滤数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定

let arr = [1,2,3];

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

 function filterNums() {
   return Promise.all(arr.filter(filter));
 }

 filterNums().then(results => {
   let l = results.length;
   // length should be 1, but is 3
 });

长度为3,因为返回了Promises,而不是值。有没有办法用返回Promise的函数过滤数组?

The length is 3 because Promises are returned, not values. Is there a way to filter the array with a function that returns a Promise?

注意:对于此示例,fs.stat已替换为setTimeout,请参阅 https://github.com/silenceisgolden/learn-esnext/blob/array-filter-async-function/tutorials /array-filter-with-async-function.js 了解特定代码。

Note: For this example, fs.stat has been replaced with setTimeout, see https://github.com/silenceisgolden/learn-esnext/blob/array-filter-async-function/tutorials/array-filter-with-async-function.js for the specific code.

推荐答案

如上所述注释, Array.prototype.filter 是同步的,因此不支持Promises。

As mentioned in the comments, Array.prototype.filter is synchronous and therefore does not support Promises.

因为你现在可以(理论上) )使用ES6的子类内置类型,您应该能够添加自己的异步方法来包装现有的过滤器函数:

Since you can now (theoretically) subclass built-in types with ES6, you should be able to add your own asynchronous method which wraps the existing filter function:

注意:我评论过out the subclassing,因为Babel还不支持Arrays

class AsyncArray /*extends Array*/ {
  constructor(arr) {
    this.data = arr; // In place of Array subclassing
  }

  filterAsync(predicate) {
     // Take a copy of the array, it might mutate by the time we've finished
    const data = Array.from(this.data);
    // Transform all the elements into an array of promises using the predicate
    // as the promise
    return Promise.all(data.map((element, index) => predicate(element, index, data)))
    // Use the result of the promises to call the underlying sync filter function
      .then(result => {
        return data.filter((element, index) => {
          return result[index];
        });
      });
  }
}
// Create an instance of your subclass instead
let arr = new AsyncArray([1,2,3,4,5]);
// Pass in your own predicate
arr.filterAsync(async (element) => {
  return new Promise(res => {
    setTimeout(() => {
      res(element > 3);
    }, 1);
  });
}).then(result => {
  console.log(result)
});

Babel REPL演示

这篇关于使用返回promise的函数过滤数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆