Array.prototype.filter
只能接受傳入 Synchronous Function,若要傳入 Asynchronous Function,可依需求使用不同方式實現。
Version
ECMAScript 2017
Synchronous filter
let data = [1, 2, 3]
let pred = x => x === 1
data.filter (pred) // ?
filter
會根據傳入 predicate 過濾,可傳入 sync function,如預期回傳新 Array。
Asynchronous filter
let data = [1, 2, 3]
let pred = async x => x === 1
data.filter (pred) // ?
若對 filter
傳入 async function,雖然沒有錯誤,但結果完全不對,因為 filter
並不支援 async function。
Promise.all + map
let data = [1, 2, 3]
let pred = async x => x === 1
let result = await Promise.all (data.map (pred))
data.filter ((x, i) => result [i]) // ?
使用 Promise.all
+ Array.prototype.map
實現 async filter
。
Array.prototype.map
搭配 Promise.all
則可接受 async function,藉由此特性先將 async function 所有結果先求得,再搭配 filter
以 lookup table 方式回傳 value。
Promise Chain
let data = [1, 2, 3]
let pred = async x => x === 1
await Promise
.all (data.map (pred))
.then (x => data.filter ((_, i) => x [i])) // ?
也可改用 Promise Chain 方式實現 async filter
。
for Loop + await
let data = [1, 2, 3]
let pred = async x => x === 1
let result = []
for (let x of data) {
if (await pred (x))
result.push (x)
}
result // ?
若覺得 Promise.all
+ map
組合較麻煩,也可簡單使用 for
loop + await
實現。
Conclusion
- 雖然
filter
無法接受 async function,但由於filter
可透過map
實現,因此可藉由Promise.all
+map
實現 asyncfilter
filter
本來就不是設計用來使用 async function,若覺得還要搭配Promise.all
太麻煩,可改用for
loop +await
較直覺,這也是少數for
loop 較適用場合
Reference
Tamas Sallai, How to Use Async Functions with Array.filter in JavaScript ?