¿Cuál es la forma correcta de manejar los errores con las transmisiones? Ya sé que hay un evento de "error" en el que puedes escuchar, pero quiero saber más detalles sobre situaciones arbitrariamente complicadas.
Para empezar, ¿qué haces cuando quieres hacer una cadena de tubería simple?
input.pipe(transformA).pipe(transformB).pipe(transformC)...
¿Y cómo se crea correctamente una de esas transformaciones para que los errores se manejen correctamente?
Más preguntas relacionadas:
- cuando ocurre un error, ¿qué sucede con el evento 'final'? ¿Nunca lo despiden? ¿A veces se despide? ¿Depende de la transformación / secuencia? ¿Cuáles son los estándares aquí?
- ¿Existen mecanismos para propagar errores a través de las tuberías?
- Por qué los dominios resuelven este problema de manera efectiva? Los ejemplos estarían bien.
- ¿Los errores que salen de los eventos de 'error' tienen rastros de pila? ¿Algunas veces? ¿Nunca? ¿hay alguna manera de obtener uno de ellos?
Promise
frameworks lo hacen mucho más simpleRespuestas:
transformar
Las secuencias de transformación son legibles y se pueden escribir y, por lo tanto, son muy buenas secuencias 'intermedias'. Por esta razón, a veces se les conoce como
through
secuencias. Son similares a una transmisión dúplex de esta manera, excepto que proporcionan una interfaz agradable para manipular los datos en lugar de simplemente enviarlos. El propósito de una secuencia de transformación es manipular los datos a medida que se canalizan a través de la secuencia. Es posible que desee hacer algunas llamadas asíncronas, por ejemplo, o derivar un par de campos, reasignar algunas cosas, etc.Para saber cómo crear una secuencia de transformación, vea aquí y aquí . Todo lo que tienes que hacer es :
_transform
método que tome a(chunk, encoding, callback)
.El fragmento son tus datos. La mayoría de las veces no tendrá que preocuparse por la codificación si está trabajando en
objectMode = true
. Se llama a la devolución de llamada cuando haya terminado de procesar el fragmento. Este fragmento se pasa a la siguiente secuencia.Si quieres un buen módulo de ayuda que le permitirá hacer a través de la corriente muy, muy fácilmente, sugiero through2 .
Para el manejo de errores, sigue leyendo.
tubo
En una cadena de tuberías, los errores de manejo no son triviales. De acuerdo con este hilo, .pipe () no está diseñado para reenviar errores. Entonces algo como ...
... solo escucharía los errores en la transmisión
c
. Si se emitiera un evento de errora
, no se transmitiría y, de hecho, se lanzaría. Para hacer esto correctamente:Ahora, aunque la segunda forma es más detallada, al menos puede mantener el contexto de dónde ocurren sus errores. Esto suele ser algo bueno.
Sin embargo, una biblioteca que encuentro útil si tiene un caso en el que solo desea capturar los errores en el destino y no le importa mucho dónde sucedió es el flujo de eventos .
final
Cuando se dispara un evento de error, el evento final no se disparará (explícitamente). La emisión de un evento de error finalizará la transmisión.
dominios
En mi experiencia, los dominios funcionan muy bien la mayor parte del tiempo. Si tiene un evento de error no controlado (es decir, emitiendo un error en una secuencia sin un oyente), el servidor puede bloquearse. Ahora, como señala el artículo anterior, puede envolver la transmisión en un dominio que debería detectar correctamente todos los errores.
La belleza de los dominios es que preservarán los rastros de la pila. Aunque event-stream también hace un buen trabajo en esto.
Para leer más, consulte el manual de transmisión . Bastante en profundidad, pero súper útil y ofrece excelentes enlaces a muchos módulos útiles.
fuente
.on('error')
controlador en una función anónima, es decira.on('error', function(e){handleError(e)})
, simplemente puede sera.on('error', handleError)
Si está usando el nodo> = v10.0.0 puede usar stream.pipeline y stream.finished .
Por ejemplo:
Vea este PR de Github para más discusión.
fuente
finished
embargo, ¿por qué usarías cuandopipeline
ya tienes una devolución de llamada?los dominios están en desuso. No los necesitas.
Para esta pregunta, las distinciones entre transformación o escritura no son tan importantes.
La respuesta de mshell_lauren es excelente, pero como alternativa, también puede escuchar explícitamente el evento de error en cada transmisión que cree que podría ser un error. y reutilice la función del controlador si lo prefiere.
hacerlo evita la infame excepción no descubierta en caso de que una de esas transmisiones active su evento de error
fuente
error
Uno también puede resolver el hecho de que cada evento es distinto; 2) ¿qué bibliotecas de streaming están escritas anteriormente, aparte de la funcionalidad nativa de Node.js? y 3) ¿por qué importa cómo manejan los eventos internamente, cuando esto obviamente le permite a alguien adjuntar controladores de errores adicionales además de lo que ya existe?Los errores de toda la cadena se pueden propagar a la secuencia más a la derecha utilizando una función simple:
que se puede usar como:
fuente
.on("error", handler)
solo se ocupa de los errores de transmisión, pero si está utilizando transmisiones de transformación personalizadas,.on("error", handler)
no detecte los errores que ocurren dentro de la_transform
función. Entonces uno puede hacer algo como esto para controlar el flujo de la aplicación:this
La palabra clave en_transform
función se refiere aStream
sí misma, que es unEventEmitter
. Por lo tanto, puede usar eltry catch
siguiente para detectar los errores y luego pasarlos a los controladores de eventos personalizados.De esta manera, puede mantener sus manejadores de lógica y error separados. Además, puede optar por manejar solo algunos errores e ignorar otros.
ACTUALIZACIÓN
Alternativa: RXJS Observable
fuente
Use el paquete multipipe para combinar varias secuencias en una secuencia dúplex. Y manejar errores en un solo lugar.
fuente
Utilice el patrón Node.js creando una mecánica de flujo de Transformación y llamando su devolución de llamada
done
con un argumento para propagar el error:fuente
Intentar capturar no capturará los errores que ocurrieron en la transmisión porque se lanzan después de que el código de llamada ya ha salido. puedes consultar la documentación:
https://nodejs.org/dist/latest-v10.x/docs/api/errors.html
fuente