Tengo una aplicación web simple que se ejecuta con NodeJS y Express. Tiene una ruta en la que un tercero externo puede enviarnos un documento XML, que luego convertimos a JSON y luego guardamos en nuestra base de datos MongoDB. Algunas cosas pueden salir mal:
El XML puede estar mal formado
La solicitud puede estar vacía
El tercero externo podría enviarnos documentos duplicados
En lugar de tener una serie interminable de bloques then(), yendo más y más profundo, sangrando más y más, quería generar una excepción para cada posible error y luego capturar esos errores en el nivel superior y procesarlos allí.
Entonces encontramos una identificación única y luego verificamos si esta identificación única ya está en MongoDB:
// will throw an error if there is a duplicate document_is_redundant(AMS_945, unique_id);La función se ve así:
function document_is_redundant(this_model, this_unique_id) { return this_model.findOne({ unique_id : this_unique_id }) .exec() .then((found_document) => { // 2021-11-28 -- if we find a duplicate, we throw an error and handle it at the end // But remember, we want to return a HTTP status code 200 to AMS, so they will stop // re-sending this XML document. if (found_document != 'null') { throw new DocumentIsRedundantException(this_unique_id); } }); // no catch() block because we want the exception to go to the top level } Esto me da: UnhandledPromiseRejectionWarning
Tal vez estoy pensando demasiado en Java en lugar de Javascript, pero supuse que si no atrapaba () la excepción en esa función, subiría al nivel superior, que es donde quiero lidiar con eso. . También asumí que interrumpiría el flujo del código en la línea donde llamo a la función.
Lamentablemente, la excepción no detectada no interrumpe el hilo principal de ejecución, por lo que el documento se guarda, incluso cuando es un duplicado.
Entonces, me quedo pensando que la única forma en que puedo hacer que esto funcione es devolver la Promesa de la función y luego tener un bloque luego () después de la llamada a la función document_is_duplicate .
No me gusta tener que anidar bloques then() dentro de bloques then(), varios niveles de profundidad. Esto parece un mal código. ¿Hay otra manera?
No estoy seguro de por qué desea arrojar un error si su documento existe. Búsquelo, Mongoose devolverá un documento si existe, o null si no existe. Entonces simplemente await el resultado. Se pueden esperar los métodos de Mongoose, y si agrega .exec() , incluso devuelven una Promesa verdadera, lo que hace que su vida sea aún más fácil:
const document_is_redundant = (this_model, unique_id) => this_model.findOne({ unique_id }).lean().exec(); // Now you use it this way if( !(await document_is_redundant(AMS_945, unique_id))){ // If the returned value is not null console.log("Document is redundant! Aborting") return; } // Returned value was null console.log("The document doesn't exist yet!")