Wie verwende ich Array.prototype.filter mit async?
Lesezeit: 5 Minuten
Hintergrund
Ich versuche, ein Array von Objekten zu filtern. Bevor ich filtere, muss ich sie in ein bestimmtes Format konvertieren, und dieser Vorgang ist asynchron.
Nun, wie einige von Ihnen vielleicht wissen, Array.protoype.filter ist eine Funktion, die Callback muss entweder wahr oder falsch zurückgeben. filter ist synchron. Im vorherigen Beispiel gebe ich keinen von ihnen zurück, ich gebe ein Promise zurück ( alle asynchronen Funktionen sind Promises ).
Also wie man annehmen kann, funktioniert der Code davor nicht wirklich… Diese Annahme ist richtig.
Problem
Damit der Filter mit einer asynchronen Funktion funktioniert, habe ich den Stackoverflow überprüft und dieses Thema gefunden:
Filtern eines Arrays mit einer Funktion, die ein Versprechen zurückgibt
Leider ist die gewählte Antwort zu komplex und verwendet Klassen. Das geht nicht für mich. Ich suche stattdessen nach einer einfacheren Lösung, die einfache Funktionen mit einem funktionalen Ansatz verwendet.
Ganz am Ende gibt es eine Lösung, die eine Karte mit einem Callback verwendet, um einen Filter zu simulieren:
https://stackoverflow.com/a/46842181/1337392
Aber ich hatte gehofft, meine Filterfunktion zu reparieren, nicht zu ersetzen.
Fragen
Gibt es eine Möglichkeit, eine asynchrone Funktion in einem Filter zu haben?
Wenn nicht, was ist der einfachste Ersatz, den ich tun kann?
Sie könnten eine vorhandene asynchrone Filterfunktion wie verwenden Array-Async-Filteroder schreiben Sie Ihre eigene.
– Matt Browne
3. November 2017 um 11:49 Uhr
Es sieht so aus, als ob die eingebaute Filterfunktion verwendet wird Function.call() unter der Haube, um Ihre Filterfunktion auszuführen. Das scheint wahrscheinlich das async/await-Bit zu unterbrechen, indem es nicht anruft await
– Paulus
3. November 2017 um 11:54 Uhr
Es gibt keine Möglichkeit, Filter mit einer asynchronen Funktion zu verwenden (zumindest die mir bekannte). Der einfachste Weg, Filter mit einer Sammlung von Promises zu verwenden, ist use Promise.all und wenden Sie dann die Funktion auf Ihre Ergebnissammlung an. Es würde in etwa so aussehen:
const result = await scramjet.fromArray(arr)
.filter(async (item) => somePromiseReturningMethod(item))
.toArray();
So einfach ist das – hier ist ein fertiges Beispiel zum Kopieren/Einfügen:
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
);
Haftungsausschluss: Ich bin der Autor von scramjet. 🙂
Jakob T.
Erstellen Sie ein paralleles Array zu Ihrem Array, für das Sie den Filter aufrufen möchten. Erwarten Sie alle Versprechungen von Ihrer Filterfunktion, in meinem Beispiel, isValid. Beim Rückruf rein filterverwenden Sie das zweite Argument, index, um in Ihr paralleles Array zu indizieren, um zu bestimmen, ob es gefiltert werden soll.
@available(macOS 10.15.0, *)
extension Array where Element: Any {
public func asyncFilter(closure: (Element) async -> Bool) async -> Array {
var result = [Element]()
for item in self {
if await closure(item) {
result.append(item)
}
}
return result
}
}
Verwendungszweck:
result = await result.asyncFilter { item in
if <item match> {
return true
}
}
14034300cookie-checkWie verwende ich Array.prototype.filter mit async?yes
Sie könnten eine vorhandene asynchrone Filterfunktion wie verwenden Array-Async-Filteroder schreiben Sie Ihre eigene.
– Matt Browne
3. November 2017 um 11:49 Uhr
Es sieht so aus, als ob die eingebaute Filterfunktion verwendet wird
Function.call()
unter der Haube, um Ihre Filterfunktion auszuführen. Das scheint wahrscheinlich das async/await-Bit zu unterbrechen, indem es nicht anruftawait
– Paulus
3. November 2017 um 11:54 Uhr