Ответ 1
Плюсы для обратных вызовов:
- Простой для понимания и создания.
- Несколько более эффективный, потому что создано меньше объектов и собран мусор.
- Node выбрал обратные вызовы
(error,result)
. Я рекомендую следовать их порядку аргумента для согласованности. (В отличие от(result1, result2, result3, error)
.)
Плюсы для promises:
- Предоставляет свободный интерфейс, который иногда может помочь уменьшить вложенный аддон обратного вызова, как показанный здесь. Код, по-видимому, протекает линейно путем цепочки вызовов
.then(foo).then(bar)
. - Хорошая библиотека promises позволит вам запускать много асинхронных операций в параллельно и продолжать, только когда все они будут завершены. Библиотека Deferred делает это без проблем через
map
, Q имеетallResolved
, а ES6 promises предлагаетPromise.all()
. (Это также возможно с обратными вызовами, например, используяasync.parallel()
, но не встроенный.) - Хорошая библиотека promises позволит вам указать одну функцию обработки ошибок, которая будет вызываться, если какая-либо из функций очереди выйдет из строя. Для этого с обратными вызовами требуется небольшой шаблон:
if (err) return callback(err);
в начале каждого обратного вызова.
Было бы разумно использовать обратные вызовы рядом с дном стека, для кода, который будет запускаться много раз в секунду. Выше стека, promises может быть предпочтительнее, так как они легче читать и понимать, и могут обрабатывать ошибки более элегантно.
Стоит отметить, что promises можно построить из callbacks во время выполнения. Таким образом, вы можете реализовать свой основной код в минимальной форме обратного вызова и по-прежнему выставлять версию библиотеки promises, если хотите. (Как в Q.nfbind()
.)
Мне было бы интересно услышать другие плюсы и минусы.
Бонусный совет: Всегда обрабатывайте ошибки! При использовании обоих методов, если вы не обрабатываете ошибку, она просто исчезнет, в результате чего вы будете в темноте о том, почему ваш код не работал должным образом.
Обратные вызовы должны всегда обрабатывать
if (err) ...
, а promises всегда должен иметь.catch()
, если они не возвращаются.Даже если вы иногда ожидаете ошибок и не нуждаетесь в их обработке, а не при обработке непредвиденных ошибок, вы не будете слышать об ошибках от ошибок разработчиков, таких как опечатки, если код будет изменен в будущем.
Альтернативой
.catch()
для promises является прослушивание необработанных отказов. Лично я использую это, чтобы выдать предупреждение о том, что.catch()
отсутствует!