Я знаю, что существует множество control flow libraries для node.js. Некоторые из них допускают одну цепочку асинхронных функций с обратными вызовами (например, async, asyncblock и т. Д.), Остальные используют promise concept (Q, отложенные, фьючерсы и т. Д.). Учитывая, что сценарий с длинными сценариями совершает ряд действий один за другим, которые могут быть неудачными в любой момент, какой поток управления вы предпочитаете и почему? Каковы плюсы и минусы?Node.js поток управления: обратные вызовы или обещания?
ответ
Я не думаю, что существует множество объективных плюсов и минусов. Async очень популярен (на основе npm packages that depend on it).
Мне нравятся библиотеки потока управления (в частности, async), потому что мне легче понять. Обещания путают меня, а асинхронность понятна. Я подозреваю, что это всего лишь кривая обучения, и обещания были бы более читабельными, если бы я потратил усилия на их изучение. Но должен ли я ожидать, что люди тоже будут читать мой код?
Существует также 3-й тип - Fibers. Волокна еще не работают в Windows, но (IMO) предлагает самый четкий синтаксис для вещей, которые должны выполняться последовательно.
Pros для обратных вызовов:
- Простой понять и создать.
- Отчасти более эффективный, поскольку создано меньше объектов и собран мусор.
- Узел выбрал
(error,result)
обратные вызовы по всему миру. Я рекомендую следовать их порядку аргумента для согласованности. (В отличии от сказать(result1, result2, result3, error)
.)
Доводов обещаний:
- Обеспечивает свободно интерфейса, который иногда может помочь смягчить вложенный обратный вызов в ад, так как shown here. Код, по-видимому, протекает линейно путем цепочки вызовов
.then(foo).then(bar)
. - Хорошая библиотека обещаний позволит вам запускать много асинхронных операций в параллельно и продолжать, только когда все они будут завершены. Библиотека Deferred делает это без проблем
map
, Q имеетallResolved
, а ES6 Promises предлагаетPromise.all()
. (Это также возможно с обратными вызовами, например, с использованиемasync.parallel()
, но не встроенным.) - В библиотеке с хорошими обещаниями вы укажете одну функцию обработки ошибок, которая будет вызываться, если какая-либо из функций очереди выйдет из строя. Для этого с обратными вызовами требуется небольшой шаблон:
if (err) return callback(err);
в начале каждого обратного вызова.
Это имело бы смысл использовать обратные вызовы вблизи нижней части стека, для кода, который будет выполняться много раз в секунду. Выше стека, обещания могут быть предпочтительнее, поскольку их легче читать и понимать, и они могут обрабатывать ошибки более элегантно.
Стоит отметить, что обещания могут быть построены из обратных вызовов во время выполнения. Таким образом, вы можете реализовать свой основной код в минимальной форме обратного вызова и по-прежнему выставлять обезболивающую версию библиотеки, если хотите. (Как в Q.nfbind()
.)
Мне было бы интересно услышать другие плюсы и минусы.
Бонус: Всегда обрабатывайте ошибки! С помощью обоих методов, если вы не обрабатываете ошибку, она просто исчезнет, в результате чего вы будете в темноте о том, почему ваш код не работает должным образом.
Обратные вызовы должны всегда обрабатывать
if (err) ...
, а обещания всегда должны иметь.catch()
, если они не возвращаются.Даже если вы иногда ожидаете ошибок и не нуждаетесь в их обработке, а не при обработке непредвиденных ошибок, вы не будете слышать об ошибках разработчиков, таких как опечатки, если код будет изменен в будущем.
Альтернатива
.catch()
для Promises заключается в прослушивании unhandled rejections. Лично я использую это, чтобы предупредить, что.catch()
отсутствует!
Я экспериментировал с декларативным подходом с этой библиотекой: http://chainsjs.org еще больше работы, чтобы сделать на нем, но это дает возможность определить «карту выполнения», где вы можете в значительной степени полностью контролировать поток выполнения из простого сопоставления.
Этот сайт был сегодня, но я нашел [копию] (http://web.archive.org/web/20141217011058/http://chainsjs.org/) в архиве. Список других библиотек потока управления [здесь] (https://github.com/joyent/node/wiki/modules#user-content-wiki-async-flow). – joeytwiddle
@joeytwiddle - спасибо за примечание, я никогда не переключал IP, когда страницы github меняли IP. Я только что обновил DNS, он должен скоро вернуться. –
Подробнее о perfs: http://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of/ – Offirmo
ссылка не работает больше – Shide
Это архивная копия Совершенная ссылка Оффирмо] (http://web.archive.org/web/20160522044854/http://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of). – joeytwiddle