Tengo un punto final de parche que toma un cuerpo de campos para actualizar, itera sobre cada campo y actualiza el valor correcto. Quiero hacer algo, enviar una respuesta una vez que se hayan hecho todas esas cosas, pero no sé cómo esperar un bucle de operaciones. Si fuera una operación singular, simplemente podría agregar .then(), pero eso no funcionaría en este caso. ¿Cuál es una solución elegante para esto?
Código:
const updateUser = (req, res) => { const db = mongoConnection.getDb(); for (key in req.body) { db.collection('users').updateOne( {username: req.query.username}, {$set: {[key]: req.body[key]}} ) } // send response once for loop is done }Puede marcar la función externa async y await cada actualización de la base de datos dentro del bucle. Entonces sabrá que una vez que se completa el bucle, se realizan todas las actualizaciones de la base de datos.
Una forma aún mejor es ejecutar las actualizaciones en paralelo, ya que no dependen unas de otras. Puede usar Promise.allSettled() , que toma una serie de promesas y las resuelve cuando finaliza la última.
const updateUser = async (req, res) => { const db = mongoConnection.getDb(); const dbUpdates = Object.entries(req.body).map((key, value) => { return db.collection('users').updateOne( { username: req.query.username }, { $set: { [key]: value }} ); }); await Promise.allSettled(dbUpdates); // Send response, at this point all DB updates are done };Creo que una respuesta fácil sería ocultar el bucle for en una función asíncrona y luego usarlo en el punto final.
const updateUserField = async () => db.collection("users").updateOne( { username: req.query.username, }, { $set: { [key]: req.body[key] }, } ); const updateUserEndpoint = (req, res) => { for (let field of req.body) { await updateUserField(field); } res.status(200).send('updated'); }Luego, para realizar pruebas, podría envolver el punto final con una función que inyecte la función misma:
const updateUserEndpoint = (userUpdateFunc) => userUpdateFunc(req, res); Este patrón se llama inyección de dependencia: al escribir pruebas unitarias para el punto final, simplemente reemplazaría userUpdateFunc con cualquier función simulada que desee usar. Esto elimina la necesidad de parchear la función en la prueba.