javascript - nodejs - ¿Cómo usar Array.prototype.filter con async?
filter javascript es6 (2)
No hay forma de usar el filtro con una función asíncrona (al menos que yo sepa). La forma más sencilla de usar el filtro con una colección de promesas es usar Promise.all
y luego aplicar la función a su colección de resultados. Se vería algo como esto:
const results = await Promise.all(your_promises)
const filtered_results = results.filter(res => //do your filtering here)
Espero eso ayude.
Fondo
Estoy tratando de filtrar una matriz de objetos. Antes de filtrar, necesito convertirlos a algún formato, y esta operación es asíncrona.
const convert = () => new Promise( resolve => {
setTimeout( resolve, 1000 );
});
Entonces, mi primer intento fue hacer algo como lo siguiente usando async / await:
const objs = [ { id: 1, data: "hello" }, { id: 2, data: "world"} ];
objs.filter( async ( obj ) => {
await convert();
return obj.data === "hello";
});
Ahora, como algunos de ustedes saben, Array.protoype.filter
es una función cuya devolución de llamada debe devolver verdadero o falso . filter
es síncrono. En el ejemplo anterior, no devuelvo ninguno de ellos, devuelvo una Promesa (todas las funciones asíncronas son Promesas).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Entonces, como se puede suponer, el código anterior realmente no funciona ... Esa suposición es correcta.
Problema
Para hacer que el filtro funcione con una función asíncrona, verifiqué stackoverflow y encontré este tema:
Filtrado de una matriz con una función que devuelve una promesa
Desafortunadamente, la respuesta elegida es demasiado compleja y usa clases. Esto no servirá para mí. En cambio, estoy buscando una solución más simple, utilizando funciones simples con un enfoque funcional.
Hay una solución al final, utilizando un mapa con una devolución de llamada para simular un filtro:
https://stackoverflow.com/a/46842181/1337392
Pero esperaba arreglar mi función de filtro, no reemplazarla.
Preguntas
- ¿Hay una manera de tener una función asíncrona dentro de un filtro?
- Si no, ¿cuál es el reemplazo más simple que puedo hacer?
Usa los métodos Scramjet fromArray / toArray ...
const result = await scramjet.fromArray(arr)
.filter(async (item) => somePromiseReturningMethod(item))
.toArray();
Tan simple como eso, aquí hay un ejemplo listo para copiar / pegar:
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: soy el autor de scramjet. :)