La Mejor Manera de Construir una Colección en el Controlador Node Mongo desde un Directorio
Hice una pregunta similar ayer a esta enlace, pero la solución fue muy fácil y no abordó realmente mi problema fundamental de no entender el control de flujo en JavaScript asíncrono. La versión resumida de lo que estoy intentando hacer es construir una colección de MongoDB a partir de un directorio de archivos JSON. Lo tenía funcionando, pero modifiqué algo y ahora el flujo es tal que el programa se ejecuta por completo y, por lo tanto, cierra la conexión antes de que se ejecuten las llamadas asincrónicas insertOne()
. Cuando las llamadas insertOne()
finalmente se ejecutan, los datos no se ingresan y recibo advertencias sobre una excepción no controlada al usar una conexión cerrada.
Soy nuevo en esto, así que si lo que estoy haciendo no es una buena práctica (no lo es), por favor avísenme y estaré encantado de cambiar las cosas para que sean confiables. El código relevante se ve básicamente así:
fs.readDirSync(dataDir).forEach(async function(file){
//lógica para construir el objeto de datos desde el archivo JSON
console.log('Insertando objeto ' + obj['ID']);
let result = await connection.insertOne(obj);
console.log('Objeto ' + result.insertedId + ' insertado.');
})
Esto está envuelto en una función async
que espero. Al colocar un mensaje console.log()
al final del flujo del programa, seguido de un while(true);
, he verificado que se imprimen todos los mensajes “Insertando objeto + obj[ID]”, pero no los siguientes mensajes “Objeto + result.insertedId + insertado” cuando el flujo llega al final del programa. Si quito el while(true);
obtengo todos los mensajes de error, porque ya no estoy bloqueando y obviamente en ese punto el cliente está cerrado. En ningún caso se construye realmente la base de datos.
Entiendo que siempre hay curvas de aprendizaje, pero es realmente frustrante no poder hacer algo tan simple como el control de flujo. Solo estoy tratando de hacer algo tan simple como “recorrer cada archivo, realizar una función en cada archivo, cerrar y salir”, que es una programación básica. Entonces, ¿cuál es la mejor manera de marcar un punto en el que el control de flujo no pasará hasta que se completen todos los intentos de inserción de datos en la colección (ya sea exitosamente o no, porque idealmente puedo usar una bandera para marcar si hubo errores)?
davy.ai
El problema con el código actual es que no espera a que se completen todas las llamadas asincrónicas
insertOne()
antes de cerrar la conexión a la base de datos MongoDB. Una forma de asegurarse de que todas las inserciones se completen antes de cerrar la conexión es usarPromise.all()
para esperar a que se resuelvan todas las promesas.Aquí hay una versión actualizada del código que utiliza
Promise.all()
:En este código actualizado, creamos un arreglo de promesas (
insertPromises
) para cada llamada ainsertOne()
, y luego usamosPromise.all()
para esperar a que se resuelvan todas las promesas. La llamada aPromise.all()
devuelve una nueva promesa que se resuelve con un arreglo de resultados cuando todas las promesas de entrada se han resuelto. Usamosawait
para esperar a que esta promesa se resuelva, y luego mostramos un mensaje que indica que todas las inserciones se han completado (o un mensaje de error si ocurrió un error). Finalmente, cerramos la conexión a la base de datos.