javascript - Javascript - 如何将Array prototype filter与async一起使用?

背景

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


 const convert = () => new Promise( resolve => {


 setTimeout( resolve, 1000 );


 });



因此,我的第一个尝试是使用async=await执行以下操作:


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



objs.filter( async ( obj ) => {


 await convert();


 return obj.data ==="hello";


});



众所周知,现在Array.prototype.filter是一个函数,回调必须返回true或false。

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

因此,可以假设,前面的代码实际上不起作用,这个假设是正确的。

问题

为了使过滤器与async函数一起工作,我检查stackoverflow并找到以下主题:

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

不幸的是,选择的答案过于复杂,使用了类,这对我不起作用,我正在寻找一个更简单的解决方案,使用简单的函数和函数方法。

最终找到了一个解决方案,使用带有回调的map模拟过滤器:

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

但是我希望修复我的过滤函数,而不是替换它。

问题

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

时间: 原作者:

没有办法使用带有异步功能的过滤器(至少我知道),你必须在一组promises中使用filter的最简单的方法是使用Promise.all函数,然后应用,它看起来像这样:


const results = await Promise.all(your_promises)


const filtered_results = results.filter(res => //do your filtering here)



希望它能帮上忙。

原作者:

使用Scramjet fromArray/toArray方法。


const result = await scramjet.fromArray(arr)


 .filter(async (item) => somePromiseReturningMethod(item))


 .toArray();



就这么简单,下面是一个复制粘贴的例子:


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


);



免责声明:我是scramjet的作者。: )

原作者:

建立一个并行数组到你想要调用filter的数组,在filter中的回调中,使用第二个参数index来决定是否应该在并行数组中索引。


// ===============================================


// common


// ===============================================


const isValid = async () => Math.random() > 0.5;


const values = Array(100).fill(42); // array of size 100 with all its values being 42



// ===============================================


// won't filter anything


// ===============================================


const filtered = values.filter(async v => await isValid());


console.log(filtered.length);



// ===============================================


// filters


// ===============================================


(async () => {


 const shouldFilter = await Promise.all(values.map(isValid));


 const filtered2 = values.filter((value, index) => shouldFilter[index]);



 console.log(filtered2.length);


})();



由于任何Promise实例都具有真实值,因此这种方法是有道理的,但乍看之下并不直观。

原作者:
...