本文譯自 "How to use async functions with Array.filter in Javascript Tamás Sallai " 。 0. 如何僅保留滿足非同步條件的元素 在 "第一篇文章中" ,我們介紹了 async / await 如何幫助處理非同步事件,但在非同步處理集 ...
本文譯自How to use async functions with Array.filter in Javascript - Tamás Sallai 。
0. 如何僅保留滿足非同步條件的元素
在第一篇文章中,我們介紹了 async / await 如何幫助處理非同步事件,但在非同步處理集合時卻無濟於事。在本文中,我們將研究該filter
函數,它可能是支持非同步函數的最直觀的方法。
1. Array.filter
該filter
函數僅保留通過條件的元素。它得到一個斷言( predicate )函數,並且此函數返回 true / false 值。結果集合僅包含斷言( predicate )返回 true 的元素。
const arr = [1, 2, 3, 4, 5];
const syncRes = arr.filter((i) => {
return i % 2 === 0;
});
console.log(syncRes);
// 2,4
2. filter 結合 map 使用
這次的非同步版本要複雜一些,它分為兩個階段。第一個通過斷言函數非同步地映射數組,從而生成true / false 值。然後第二步是利用第一步的結果同步 filter
const arr = [1, 2, 3, 4, 5];
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
或單行實現:
const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate))
.then((results) => arr.filter((_v, index) => results[index]));
併發
上面的實現同時運行所有斷言函數。通常,這很好,但是與所有其他功能一樣,它可能會使某些資源變得過分緊張。幸運的是,由於上述實現依賴於此map
,因此可以使用相同的併發控制項。
4. filter 結合 reduce 使用
除了使用非同步map
與同步之外filter
,非同步reduce
也可以完成這項工作。由於它只是一個功能,因此即使沒有提供相同級別的控制,結構也更加容易。
首先,從一個空數組([]
)開始。然後通過斷言函數運行下一個元素,如果通過則將其追加到數組。如果沒有,請跳過它。
// concurrently
const asyncFilter = async (arr, predicate) =>
arr.reduce(async (memo, e) =>
await predicate(e) ? [...await memo, e] : memo
, []);
請註意,await predicate(e)
在 await memo
之前,這意味著這些將並行調用。
順序處理
要在調用下一個謂詞函數之前等待其結束,請更改await
的順序:
// sequentially
const asyncFilter = async (arr, predicate) =>
arr.reduce(async (memo, e) =>
[...await memo, ...await predicate(e) ? [e] : []]
, []);
此實現等待上一個元素,然後根據斷言(...[e]
或...[]
)的結果有條件地附加一個元素。
5. 結論
雖然非同步filter
是可能的,但它最初的工作方式看起來很奇怪。儘管併發控制仍然可用,但與其他非同步功能相比,它們需要更多的計划去控制它。