Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

164
Visualizações
¿Por qué estos rechazos de promesas son globales?

Tenemos una base de código bastante compleja en NodeJS que ejecuta muchas promesas de forma sincrónica. Algunos de ellos provienen de Firebase ( firebase-admin ), algunos de otras bibliotecas de Google Cloud, algunos son solicitudes locales de MongoDB. Este código funciona en general bien, se cumplen millones de promesas en el transcurso de 5 a 8 horas.

Pero a veces recibimos promesas rechazadas debido a razones externas como tiempos de espera de la red. Por esta razón, tenemos bloques de prueba y captura en todas las llamadas de Firebase, Google Cloud o MongoDB (las llamadas están en await , por lo que una promesa rechazada debe ser capturada como los bloques de captura). Si se agota el tiempo de espera de la red, lo intentamos nuevamente después de un tiempo. Esto funciona muy bien la mayor parte del tiempo. A veces, todo funciona sin ningún problema real.

Sin embargo, a veces aún se rechazan promesas no controladas, que luego aparecen en el process.on('unhandledRejection', ...) . Los rastros de pila de estos rechazos se ven así, por ejemplo:

 Warn: Unhandled Rejection at: Promise [object Promise] reason: Error stack: Error: at new ApiError ([repo-path]\node_modules\@google-cloud\common\build\src\util.js:59:15) at Util.parseHttpRespBody ([repo-path]\node_modules\@google-cloud\common\build\src\util.js:194:38) at Util.handleResp ([repo-path]\node_modules\@google-cloud\common\build\src\util.js:135:117) at [repo-path]\node_modules\@google-cloud\common\build\src\util.js:434:22 at onResponse ([repo-path]\node_modules\retry-request\index.js:214:7) at [repo-path]\node_modules\teeny-request\src\index.ts:325:11 at runMicrotasks (<anonymous>) at processTicksAndRejections (node:internal/process/task_queues:96:5)

Este es un seguimiento de pila que está completamente separado de mi propio código, por lo que no tengo ni idea de dónde podría mejorar mi código para hacerlo más robusto contra errores (el mensaje de error también parece ser muy útil).

Otro ejemplo:

 Warn: Unhandled Rejection at: Promise [object Promise] reason: MongoError: server instance pool was destroyed stack: MongoError: server instance pool was destroyed at basicWriteValidations ([repo-path]\node_modules\mongodb\lib\core\topologies\server.js:574:41) at Server.insert ([repo-path]\node_modules\mongodb\lib\core\topologies\server.js:688:16) at Server.insert ([repo-path]\node_modules\mongodb\lib\topologies\topology_base.js:301:25) at OrderedBulkOperation.finalOptionsHandler ([repo-path]\node_modules\mongodb\lib\bulk\common.js:1210:25) at executeCommands ([repo-path]\node_modules\mongodb\lib\bulk\common.js:527:17) at executeLegacyOperation ([repo-path]\node_modules\mongodb\lib\utils.js:390:24) at OrderedBulkOperation.execute ([repo-path]\node_modules\mongodb\lib\bulk\common.js:1146:12) at BulkWriteOperation.execute ([repo-path]\node_modules\mongodb\lib\operations\bulk_write.js:67:10) at InsertManyOperation.execute ([repo-path]\node_modules\mongodb\lib\operations\insert_many.js:41:24) at executeOperation ([repo-path]\node_modules\mongodb\lib\operations\execute_operation.js:77:17)

Al menos este mensaje de error dice algo.

Todas mis llamadas a Google Cloud o MongoDB tienen bloques de await e try : catch a su alrededor (y la referencia de MongoDB se recrea en el bloque de captura), por lo que si la promesa se rechaza dentro de esas llamadas, el error se detectaría en el bloque de captura.

A veces ocurre un problema similar en la biblioteca de Firebase. Algunas de las promesas rechazadas (por ejemplo, debido a errores de red) quedan atrapadas en nuestros bloques try-catch, pero otras no, y no tengo posibilidad de mejorar mi código, porque no hay seguimiento de pila en ese caso.

Ahora, independientemente de las causas específicas de estos problemas: encuentro muy frustrante que los errores ocurran a escala global ( process.on('unhandledRejection', ...) , en lugar de en una ubicación en mi código donde puedo manejarlos con un intento de captura Esto nos hace perder mucho tiempo, porque tenemos que reiniciar todo el proceso cuando llegamos a ese estado.

¿Cómo puedo mejorar mi código para que estas excepciones globales no vuelvan a ocurrir? ¿Por qué estos errores son rechazos globales no controlados cuando tengo bloques de intento y captura alrededor de todas las promesas?

Puede darse el caso de que estos sean los problemas de los clientes de MongoDB/Firebase: sin embargo, más de una biblioteca se ve afectada por este comportamiento, por lo que no estoy seguro.

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

un stacktrace que está completamente separado de mi propio código

Sí, pero ¿la función a la que llama tiene un manejo de errores adecuado para lo que hace TI ?
A continuación, muestro un ejemplo simple de por qué su código externo con try/catch simplemente no puede evitar los rechazos de promesas.

 //if a function you don't control causes an error with the language itself, yikes //and for rejections, the same(amount of YIKES) can happen if an asynchronous function you call doesn't send up its rejection properly //the example below is if the function is returning a custom promise that faces a problem, then does `throw err` instead of `reject(err)`) //however, there usually is some thiAPI.on('error',callback) but try/catch doesn't solve everything async function someFireBaseThing(){ //a promise is always returned from an async function(on error it does the equivalent of `Promise.reject(error)`) //yet if you return a promise, THAT would be the promise returned and catch will only catch a `Promise.reject(theError)` return await new Promise((r,j)=>{ fetch('x').then(r).catch(e=>{throw e}) //unhandled rejection occurs even though e gets thrown //ironically, this could be simply solved with `.catch(j)` //check inspect element console since stackoverflow console doesn't show the error }) } async function yourCode(){ try{console.log(await someFireBaseThing())} catch(e){console.warn("successful handle:",e)} } yourCode()

Al leer su pregunta una vez más, parece que puede establecer un límite de tiempo para una tarea y luego throw manualmente a su catch de espera si lleva demasiado tiempo (porque si la pila de errores no incluye su código, la promesa que recibe mostrado a unhandledRejection probablemente no sería visto por su código en primer lugar)

 function handler(promise,time){ //automatically rejects if it takes too long return new Promise(async(r,j)=>{ try{let temp=await promise; r(temp)} catch(err){j(err)} setTimeout(()=>j('promise did not resolve in given time'),time) }) } async function yourCode(){ while(true){ //will break when promise is successful(and returns) try{return await handler(someFireBaseThing(...someArguments),1e4)} catch(err){yourHandlingOn(err)} } }
over 4 years ago · Santiago Trujillo Relatório

0

Desarrollando mi comentario, esto es lo que apuesto a que está sucediendo: configura una instancia base de ordenación para interactuar con la API, luego usa esa instancia para avanzar en sus llamadas. Es probable que esa instancia base sea un emisor de eventos que en sí mismo puede emitir un evento de 'error', que es un error fatal no controlado sin una configuración de escucha de 'error'.

Usaré postgres como ejemplo, ya que no estoy familiarizado con firebase o mongo.

 // Pool is a pool of connections to the DB const pool = new (require('pg')).Pool(...); // Using pool we call an async function in a try catch try { await pool.query('select foo from bar where id = $1', [92]); } catch(err) { // A SQL error like no table named bar would be caught here. // However a connection error would be emitted as an 'error' // event from pool itself, which would be unhandled }

La solución en el ejemplo sería comenzar con

 const pool = new (require('pg')).Pool(...); pool.on('error', (err) => { /* do whatever with error */ })
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda