
本文譯自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是可能的,但它最初的作業方式看起來很奇怪,盡管并發控制仍然可用,但與其他異步功能相比,它們需要更多的計劃去控制它,
推薦閱讀
-
如何在 Array.forEach 中正確使用 Async
-
如何在 Vue中優雅的使用防抖節流

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/123514.html
標籤:JavaScript
