使用返回承诺的函数过滤数组 [英] Filtering an array with a function that returns a 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:
注意:我已经注释掉了子类化,因为 Babel 目前还不支持数组
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)
});
这篇关于使用返回承诺的函数过滤数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!