如何使用Array.prototype.filter与异步?

Fla*_*nix 27 javascript arrays filter async-await

背景

我试图过滤一个对象数组.在我过滤之前,我需要将它们转换为某种格式,并且此操作是异步的.

 const convert = () => new Promise( resolve => {
     setTimeout( resolve, 1000 );
 });
Run Code Online (Sandbox Code Playgroud)

所以,我的第一次尝试是使用async/await执行以下操作:

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

objs.filter( async ( obj ) => {
    await convert();
    return obj.data === "hello";
});
Run Code Online (Sandbox Code Playgroud)

现在,正如你们中的一些人所知,Array.protoype.filter回调必须返回true或false的函数.filter是同步的.在前面的例子中,我没有返回它们,我返回一个Promise(所有异步函数都是Promises).

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

因此,正如人们可以假设的那样,之前的代码并没有真正起作用......这种假设是正确的.

问题

为了使过滤器使用异步函数,我检查了stackoverflow并找到了这个主题:

使用返回promise的函数过滤数组

不幸的是,选择的答案过于复杂并且使用了类.这不适合我.我正在寻找一个更简单的解决方案,使用功能方法的简单功能.

最后有一个解决方案,使用带回调的地图来模拟过滤器:

/sf/answers/3278952701/

但我希望修复我的过滤功能,而不是替换它.

问题

  • 有没有办法在过滤器内部使用异步功能?
  • 如果没有,我能做的最简单的替换是什么?

小智 25

没有办法使用具有异步功能的过滤器(至少我知道).您必须使用带有promise集合的过滤器的最简单方法是使用Promise.all然后将该函数应用于您的结果集合.它看起来像这样:

const results = await Promise.all(your_promises)
const filtered_results = results.filter(res => //do your filtering here)
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.

  • 我是承诺的新手,your_promises 参数是什么?我的函数会返回一个承诺对象吗? (3认同)
  • @OmarRuder 一个可迭代的(例如数组)承诺。 (2认同)

ce-*_*oco 5

改编自文章How to use async functions with Array.filter in Javascript by Tamás Sallai,您基本上有两个步骤:

  1. 一种为物体通过创造条件的
  2. 接收对象并根据条件返回 true 或 false 的一种

这是一个例子

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

function sleep(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    }

const asyncFilter = async (arr, predicate) => {
    const results = await Promise.all(arr.map(predicate));

    return arr.filter((_v, index) => results[index]);
}

const asyncRes = await asyncFilter(arr, async (i) => {
    await sleep(10);
    return i % 2 === 0;
});

console.log(asyncRes);
// 2,4
Run Code Online (Sandbox Code Playgroud)