2012-02-22 1 views
18

Я знаю, что существует множество control flow libraries для node.js. Некоторые из них допускают одну цепочку асинхронных функций с обратными вызовами (например, async, asyncblock и т. Д.), Остальные используют promise concept (Q, отложенные, фьючерсы и т. Д.). Учитывая, что сценарий с длинными сценариями совершает ряд действий один за другим, которые могут быть неудачными в любой момент, какой поток управления вы предпочитаете и почему? Каковы плюсы и минусы?Node.js поток управления: обратные вызовы или обещания?

ответ

5

Я не думаю, что существует множество объективных плюсов и минусов. Async очень популярен (на основе npm packages that depend on it).

Мне нравятся библиотеки потока управления (в частности, async), потому что мне легче понять. Обещания путают меня, а асинхронность понятна. Я подозреваю, что это всего лишь кривая обучения, и обещания были бы более читабельными, если бы я потратил усилия на их изучение. Но должен ли я ожидать, что люди тоже будут читать мой код?

Существует также 3-й тип - Fibers. Волокна еще не работают в Windows, но (IMO) предлагает самый четкий синтаксис для вещей, которые должны выполняться последовательно.

13

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() отсутствует!

+1

Подробнее о perfs: http://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of/ – Offirmo

+0

ссылка не работает больше – Shide

+1

Это архивная копия Совершенная ссылка Оффирмо] (http://web.archive.org/web/20160522044854/http://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of). – joeytwiddle

0

Я экспериментировал с декларативным подходом с этой библиотекой: http://chainsjs.org еще больше работы, чтобы сделать на нем, но это дает возможность определить «карту выполнения», где вы можете в значительной степени полностью контролировать поток выполнения из простого сопоставления.

+0

Этот сайт был сегодня, но я нашел [копию] (http://web.archive.org/web/20141217011058/http://chainsjs.org/) в архиве. Список других библиотек потока управления [здесь] (https://github.com/joyent/node/wiki/modules#user-content-wiki-async-flow). – joeytwiddle

+0

@joeytwiddle - спасибо за примечание, я никогда не переключал IP, когда страницы github меняли IP. Я только что обновил DNS, он должен скоро вернуться. –