¿Cómo detener la cadena de promesas después de resolver?

Quiero detener la cadena de promesas después de que se resuelva a través de algunas condiciones. El siguiente código puede ser útil para entender lo que estoy diciendo.

function update(id, data) { return new Promise((resolve, reject) => { let conn; pool.get() .then((db) => { conn = db; if(Object.keys(data).length === 0) { return resolve({ updated: 0 }); } else { return generateHash(data.password); } }) .then((hash) => { conn.query("UPDATE ... ", (err, queryResult) => { if(err) { throw err; } resolve({ updated: queryResult.affectedRows }); }); }) .catch((err) => { ... }) }); } 

Tenga en cuenta que pool.get () es una API envuelta en promesa para obtener el pool de conexiones del módulo MySQL que realicé.

Lo que estoy tratando de hacer es actualizar los datos del usuario. Y para guardar recursos del servidor, evité actualizar si no hay datos para actualizar (Object.keys (data) .length === 0).

Cuando probé este código, el segundo (actualización de la base de datos) siempre está sucediendo, incluso si no hay datos para actualizar.

Leí este post , pero no funcionó. ¿Por qué no se detuvo la cadena de promesas cuando llamé “devolver resolver ();”? ¿Y cómo lo paro correctamente? Realmente me gusta usar Promises, pero a veces, este tipo de cosas me vuelven loco. Estaré muy agradecido de ayudarme con este problema. ¡Gracias!

PS Estoy usando el nodo v6.2.2 de todos modos.

¿Por qué no se detuvo la cadena de promesas cuando llamé “devolver resolver ();”?

Has regresado de la callback actual then y has cumplido la promesa externa. Pero eso no “detiene” nada, entonces la cadena continuará resolviéndose con el valor de retorno de la callback.

¿Y cómo lo paro correctamente?

Debe poner la llamada a then dentro if desea que la condición se aplique a ella:

 pool.get() .then((db) => { … if (Object.keys(data).length === 0) { …({ updated: 0 }); } else { return generateHash(data.password) .then((hash) => { conn.query("UPDATE ... ", (err, queryResult) => { … }); }) } }) .catch((err) => { ... }) 

¡Y en cualquier caso, debes evitar el constructor Promise antipatrón ! Solo debes promisificar el método de query :

 function query(conn, cmd) { return new Promise((resolve, reject) => { conn.query(cmd, (err, queryResult) => { if (err) reject(err); // Don't throw! else resolve(queryResult); }); }); } 

y luego usar eso:

 function update(id, data) { return pool.get() .then(conn => { if (Object.keys(data).length === 0) { conn.close(); // ??? return { updated: 0 }; } else { return generateHash(data.password) .then(hash => { return query(conn, "UPDATE ... ") }).then(queryResult => { conn.close(); // ??? return { updated: queryResult.affectedRows }; }, err => { … conn.close(); // ??? }); } }); } 

Tenga en cuenta que es posible que no tenga sentido obtener una conexión del grupo si puede saber de antemano que no se realizará ninguna consulta, por lo que probablemente debería poner el if en el nivel superior:

 function update(id, data) { if (Object.keys(data).length === 0) { return Promise.resolve({ updated: 0 }); } else { return pool.get() .then(conn => { return generateHash(data.password) .then(hash => { return query(conn, "UPDATE ... ") }).then(queryResult => { conn.close(); // ??? return { updated: queryResult.affectedRows }; }, err => { … conn.close(); // ??? }); }); } } 

Esta sería una buena situación para usar una sentencia if :

 function update(id, data) { if (Object.keys(data).length === 0) { return Promise.resolve({ updated: 0 }); } let conn; return pool.get() .then((db) => { conn = db; return generateHash(data.password); }) .then((hash) => { return new Promise(function (resolve, reject) { conn.query("UPDATE ... ", (err, queryResult) => { if(err) { reject(err); } resolve({ updated: queryResult.affectedRows }); }); }); }) .catch((err) => { ... }) }