Как правильно обрабатывать ошибки в потоках? Я уже знаю, что есть событие «ошибка», которое вы можете прослушать, но я хочу знать некоторые подробности о сколь угодно сложных ситуациях.
Для начала, что вы делаете, когда хотите создать простую цепочку труб:
input.pipe(transformA).pipe(transformB).pipe(transformC)...
И как правильно создать одно из этих преобразований, чтобы ошибки обрабатывались правильно?
Более связанные вопросы:
- когда происходит ошибка, что происходит с событием 'end'? Разве его никогда не уволят? Это иногда увольняют? Зависит ли это от преобразования / потока? Какие стандарты здесь?
- Есть ли механизмы для распространения ошибок через трубы?
- домены решают эту проблему эффективно? Примеры были бы хорошими.
- ошибки, возникающие в результате событий 'error', имеют следы стека? Иногда? Никогда? Есть ли способ получить один из них?
Promise
рамки делают это намного прощеОтветы:
преобразование
Потоки преобразования являются как читаемыми, так и записываемыми, и поэтому являются действительно хорошими «средними» потоками. По этой причине их иногда называют
through
потоками. В этом смысле они похожи на дуплексный поток, за исключением того, что они предоставляют удобный интерфейс для манипулирования данными, а не просто для их отправки. Цель потока преобразования состоит в том, чтобы манипулировать данными при их передаче по потоку. Вы можете, например, сделать несколько асинхронных вызовов или получить пару полей, переназначить некоторые вещи и т. Д.Как создать поток преобразования смотрите здесь и здесь . Все, что вам нужно сделать, это:
_transform
метод, который принимает(chunk, encoding, callback)
.Кусок - это ваши данные. Большую часть времени вам не нужно беспокоиться о кодировании, если вы работаете в
objectMode = true
. Обратный вызов вызывается, когда вы закончите обработку чанка. Этот кусок затем передается следующему потоку.Если вам нужен хороший вспомогательный модуль, который позволит вам действительно легко выполнять потоковую передачу , я предлагаю использовать via2 .
Для обработки ошибок, продолжайте читать.
труба
В цепочке труб обработка ошибок действительно нетривиальна. Согласно этой теме .pipe () не создан для пересылки ошибок. Так что-то вроде ...
... будет только слушать ошибки в потоке
c
. Если произошла ошибкаa
, она не будет передана и, на самом деле, выдастся. Чтобы сделать это правильно:Теперь, хотя второй способ более многословен, вы можете, по крайней мере, сохранить контекст, где происходят ваши ошибки. Обычно это хорошая вещь.
Одна библиотека, которую я нахожу полезной, хотя, если у вас есть случай, когда вы хотите захватить только ошибки в месте назначения, и вас не волнует, где это произошло, это поток событий .
конец
Когда происходит событие ошибки, событие завершения не будет запущено (явно). Излучение события ошибки завершит поток.
домены
По моему опыту, домены работают очень хорошо большую часть времени. Если у вас есть необработанное событие ошибки (т.е. выдается ошибка в потоке без прослушивателя), сервер может дать сбой. Теперь, как указано в приведенной выше статье, вы можете заключить поток в домен, который должен правильно отлавливать все ошибки.
Прелесть доменов в том, что они сохранят следы стека. Хотя Event-Stream также хорошо справляется с этой задачей.
Для дальнейшего чтения, ознакомьтесь со справочником . Довольно подробно, но очень полезно и дает отличные ссылки на множество полезных модулей.
источник
.on('error')
обработчик в анонимную функцию, т.a.on('error', function(e){handleError(e)})
a.on('error', handleError)
Если вы используете узел> = v10.0.0, вы можете использовать stream.pipeline и stream.finished .
Например:
Смотрите этот github PR для дальнейшего обсуждения.
источник
finished
, когдаpipeline
уже есть обратный вызов?домены устарели. они тебе не нужны.
в этом вопросе различия между преобразованием или записью не так важны.
Ответ mshell_lauren великолепен, но в качестве альтернативы вы также можете явно прослушивать событие ошибки в каждом потоке, который, по вашему мнению, может быть ошибочным. и повторно использовать функцию обработчика, если вы предпочитаете.
это предотвращает печально известное неперехваченное исключение, если один из этих потоков запускает событие ошибки
источник
error
можно также согласиться с тем фактом, что каждое событие отличается; 2) какие потоковые библиотеки написаны выше, кроме родной функциональности Node.js? и 3) почему имеет значение, как они обрабатывают события внутри, когда это, очевидно, позволяет кому-либо присоединять дополнительные обработчики ошибок поверх того, что уже есть?Ошибки всей цепочки можно распространить на самый правый поток с помощью простой функции:
который можно использовать как:
источник
.on("error", handler)
заботится только об ошибках потока, но если вы используете пользовательские потоки преобразования,.on("error", handler)
не улавливайте ошибки, происходящие внутри_transform
функции. Таким образом, можно сделать что-то вроде этого для управления потоком приложений:this
Ключевое слово в_transform
функции относится кStream
самому себе, который являетсяEventEmitter
. Таким образом, вы можете использовать,try catch
как показано ниже, чтобы перехватить ошибки, а затем передать их в пользовательские обработчики событий.Таким образом, вы можете хранить свою логику и обработчики ошибок отдельно. Кроме того, вы можете обрабатывать только некоторые ошибки и игнорировать другие.
ОБНОВЛЕНИЕ
Альтернатива: наблюдаемые RXJS
источник
Используйте пакет multiipe для объединения нескольких потоков в один дуплексный поток. И обрабатывать ошибки в одном месте.
источник
Используйте шаблон Node.js, создав механику потока Transform и вызвав его обратный вызов
done
с аргументом для распространения ошибки:источник
Try catch не будет регистрировать ошибки, которые произошли в потоке, потому что они генерируются после того, как вызывающий код уже завершился. Вы можете обратиться к документации:
https://nodejs.org/dist/latest-v10.x/docs/api/errors.html
источник