Digamos que tenemos esta función con errores:
async function buggy() { while(true) { await new Promise(resolve => setTimeout(resolve, 1000)); } }Si lo llama en algún lugar de NodeJS, ¿afectaría permanentemente el rendimiento del servidor?
Si es así, ¿sería mejor poner siempre un mecanismo a prueba de fallas como este para todas las promesas que no son de confianza?
new Promise((resolve, reject) => { buggy().then(() => resolve); setTimeout(reject, 10000); };No, no hay nada malo con su función de buggy . Decir que una promesa se ejecuta es engañoso: una promesa no se ejecuta. Es un objeto que ha proporcionado una devolución de llamada. Mientras no se llame a la resolve de devolución de llamada y no se llame a su método then , no sucederá nada con ese objeto de promesa.
Lo siguiente sucede cuando se ejecuta buggy :
new Promise crea un objeto de promesasetTimeout se ejecuta y se completa inmediatamente. Registra la devolución de llamada de resolve .await , que en realidad llama then la promesa anterior de agregar un oyente, y hace que el retorno sea buggy . Si es la primera vez, devuelve una promesa pendiente a la persona que llama.buggy ), la API setTimeout colocará la devolución de llamada de resolve en la cola de trabajo relevante.resolve ) pone la promesa en un estado resuelto y envía una notificación para sus oyentes (incluido el creado por await ) como un trabajo en la cola de trabajos de promesa.buggy , que luego continúa con su bucle. El impacto en el motor o la memoria es comparable con una llamada a setInterval que nunca borra con clearInterval . Hay un poco más de sobrecarga debido a los trabajos adicionales relacionados con la promesa (además del trabajo del temporizador regular) que se activan después de cada segundo, y el estado de ejecución guardado de buggy , que es comparable con lo que tendría con un infinito generador (usando yield ).
En el caso de que el estado de resolución de la promesa dependa de un recurso/temporizador externo que nunca termina (infinito como la duración), la seguridad sugerida funcionaría y el rendimiento del servidor no se vería tan afectado.
// this won't stuck and the fail-safe will work // (ignore the timer not being cleaned) function buggy() { return new Promise(resolve => setTimeout(resolve, Infinity)); }De lo contrario (en caso de que la promesa sea únicamente síncrona, es decir, la resolución depende de un ciclo infinito que nunca termina), nunca se llamaría a la función de rechazo ya que el ciclo de eventos está atascado, lo que bloqueará el servidor.
// The fail-safe wouldn't work and the server is stuck async function buggy() { while(true); }Editar: como lo señaló @Vlaz , en caso de que la función con errores sea similar a esta:
async function buggy() { while(true) { await new Promise(resolve => setTimeout(resolve, 1000)); } }El mecanismo de seguridad funcionaría y el servidor no se atascaría.
Edición 2: en ambos casos, no necesitará una protección contra fallas porque si funciona, significa que el código no atascó el bucle de eventos y también llamar a rechazar la promesa no aborta la falla.