Ответ 1
Почему не был создан api таким образом, чтобы для функции then была передана функция разрешения и отклонения, как исходный конструктор обещаний?
Фактически, API в этой спецификации стал консенсусом среди различных реализаций. Однако некоторые моменты, которые могли бы привести к этому, следующие:
-
then
- довольно функциональный метод. Этот обратный вызов должен принимать только один аргумент данных, значение результата обещания. - Передача дополнительных функций
resolve
/reject
для обратного вызова не работает с несколькими аргументами или даже с вариационными функциями. -
then
обычно используется как простая функция сопоставления. Вы простоreturn
новое значение, не требуетсяresolve
. - Когда вы действительно хотите сделать что-то асинхронное в своем обратном вызове, где вы можете использовать
resolve
/reject
, вам лучше использовать обещание в любом случае, которое вы просто можете вернуть.
Я однажды реализовал Promise lib с необязательными аргументами resolve
/reject
, но было утомительно использовать - и я редко нуждался в них из-за # 4. Использование их было подвержено ошибкам, вы могли бы легко забыть что-то (например, ошибки обработки или события прогресса) - точно так же, как люди, которые вручную создают и возвращают отложенные ответы, которые разрешены из обещаний callback, вместо вызова then
.
Исключения являются тяжелыми, поэтому кажется странным, что они используют их как выбор для управления потоком.
Они не предназначены для использования в потоке управления (например, ветвление, петли и т.д.), но для обработки исключений: отклонения являются исключительными, Большинство разработчиков Promise хотели реализовать их в качестве альтернативы синхронному (блокирующему) коду - где IO всегда бросали исключения, поэтому они адаптировали это. Отклонения по-прежнему объясняются как асинхронный эквивалент try … catch
, хотя их монадический характер может быть использован более мощными способами и приложениями более высокого уровня.
Создание целого нового объекта обещания и его возврат, просто чтобы отклонить его, добавляет код раздувания IMO.
Здесь нет большой разницы между return new RejectedPromise(…)
, return reject(…)
и throw Error(…)
.
Отладка становится сложнее и в случае возникновения исключения (например, синтаксические ошибки или функция вызывается на объект undefined и т.д.)
Большинство разработчиков Promise, похоже, считают это преимуществом на самом деле - (неожиданные) исключения, даже в асинхронном коде, будут автоматически пойманы, поэтому их можно обработать, а не взорвать программу (незаметно). См. Также обработка исключений, сброшенные ошибки в promises и приемлемый шаблон обещания для ошибок LOUD?.