J'essaie de filtrer un tableau d'objets. Avant de filtrer, je dois les convertir au format souhaité et cette opération est asynchrone.
const convert = () => new Promise( resolve => {
setTimeout( resolve, 1000 );
});
Donc, mon premier essai a été de faire quelque chose comme ce qui suit en utilisant async/wait:
const objs = [ { id: 1, data: "hello" }, { id: 2, data: "world"} ];
objs.filter( async ( obj ) => {
await convert();
return obj.data === "hello";
});
Comme certains d'entre vous le savent peut-être, Array.protoype.filter
est une fonction pour laquelle callback doit renvoyer true ou false. filter
est synchrone. Dans l'exemple précédent, je n'en renvoie aucun, je retourne une promesse (toutes les fonctions asynchrones sont des promesses).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Donc, comme on peut le supposer, le code avant ne fonctionne pas vraiment ... Cette hypothèse est correcte.
Pour que le filtre fonctionne avec une fonction asynchrone, j'ai vérifié stackoverflow et trouvé le sujet suivant:
Filtrer un tableau avec une fonction qui retourne une promesse
Malheureusement, la réponse choisie est trop complexe et utilise des classes. Cela ne va pas pour moi. Je cherche plutôt une solution plus simple, utilisant des fonctions simples avec une approche fonctionnelle.
Il existe une solution à la fin, utilisant une carte avec un rappel pour simuler un filtre:
https://stackoverflow.com/a/46842181/1337392
Mais j'espérais corriger ma fonction de filtre, pas pour la remplacer.
Il n’existe aucun moyen d’utiliser un filtre avec une fonction asynchrone (du moins, à ma connaissance) . Le moyen le plus simple d’utiliser un filtre avec une collection de promesses consiste à utiliser Promise.all
, puis à appliquer la fonction à resultats . Cela ressemblerait à quelque chose comme ceci:
const results = await Promise.all(your_promises)
const filtered_results = results.filter(res => //do your filtering here)
J'espère que ça aide.
Utilisez méthodes Scramjet fromArray/toArray ...
const result = await scramjet.fromArray(arr)
.filter(async (item) => somePromiseReturningMethod(item))
.toArray();
aussi simple que cela - voici un exemple prêt à copier/coller:
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
);
Disclamer: Je suis l'auteur de scramjet. :)