Я писал код, который делает что-то похожее на:
function getStuffDone(param) { | function getStuffDone(param) {
var d = Q.defer(); /* or $q.defer */ | return new Promise(function(resolve, reject) {
// or = new $.Deferred() etc. | // using a promise constructor
myPromiseFn(param+1) | myPromiseFn(param+1)
.then(function(val) { /* or .done */ | .then(function(val) {
d.resolve(val); | resolve(val);
}).catch(function(err) { /* .fail */ | }).catch(function(err) {
d.reject(err); | reject(err);
}); | });
return d.promise; /* or promise() */ | });
} | }
Кто-то сказал мне, что это называется « отложенный антипаттерн » или « Promise
конструктор антипаттерн » соответственно. Что плохого в этом коде и почему он называется антипаттерном ?
javascript
promise
q
bluebird
es6-promise
Бенджамин Грюнбаум
источник
источник
getStuffDone
оболочку функции и просто использовать литерал Promise?catch
блок вgetStuffDone
обертке антипаттерн?Promise
примера у вас также есть ненужные функции обертки для.then
и.catch
обработчиков (т.е. это может быть просто.then(resolve).catch(reject)
.) Идеальным штормом анти-паттернов.Ответы:
Отложили антипаттерны (теперь явно-строительная антипаттерн) придумано Esailija являются общими антипаттернами людей , которые являются новыми для обещания сделать, я сделал это само , когда я впервые использовал слово. Проблема с приведенным выше кодом заключается в том, что он не может использовать тот факт, что обещает цепь.
Обещания могут соединяться,
.then
и вы можете вернуть обещания напрямую. Ваш код вgetStuffDone
может быть переписан как:Обещания направлены на то, чтобы сделать асинхронный код более читабельным и вести себя как синхронный код, не скрывая этого факта. Обещания представляют собой абстракцию над значением одноразовой операции, они абстрагируют понятие оператора или выражения в языке программирования.
Вы должны использовать отложенные объекты только при преобразовании API в обещания и не можете делать это автоматически, или когда вы пишете функции агрегации, которые проще выразить таким образом.
Цитируя Esailija:
источник
.defer()
одобряет API в новом (и безопасном для использования) конструкторе обещаний, но не (ни в коем случае) не отвергает идею создания обещаний :)Что с этим не так?
Повезло тебе. К сожалению, это, вероятно, не так, как вы, вероятно, забыли какой-то крайний случай. В более чем половине случаев, которые я видел, автор забыл позаботиться об обработчике ошибок:
Если другое обещание будет отклонено, это произойдет незамеченным, вместо того, чтобы распространяться на новое обещание (где оно будет обработано) - и новое обещание остается навсегда ожидающим, что может вызвать утечки.
То же самое происходит в том случае, если ваш код обратного вызова вызывает ошибку - например, когда
result
нетproperty
и выдается исключение. Это было бы необработанным и оставило бы новое обещание нерешенным.Напротив, использование
.then()
автоматически позаботится об обоих этих сценариях и отклонит новое обещание при возникновении ошибки:Отложенный антипаттерн не только громоздок, но и подвержен ошибкам . Использование
.then()
для создания цепочек намного безопаснее.В самом деле? Хорошо. Тем не менее, это будет довольно подробно и обильно, особенно если вы используете библиотеку обещаний, которая поддерживает другие функции, такие как отмена или передача сообщений. Или, может быть, в будущем, или вы хотите поменять свою библиотеку на лучшую? Вы не захотите переписать свой код для этого.
Методы библиотек (
then
) не только изначально поддерживают все функции, они также могут иметь определенные оптимизации. Их использование, скорее всего, сделает ваш код быстрее или, по крайней мере, позволит оптимизировать будущие изменения библиотеки.Как мне этого избежать?
Поэтому, когда вы обнаруживаете, что создаете вручную
Promise
илиDeferred
уже задействованы уже существующие обещания, сначала проверьте API библиотеки . Отложенный антипаттерн часто применяется людьми, которые видят обещания [только] как образец наблюдателя - но обещания - это больше, чем обратные вызовы : они должны быть составными. Каждая приличная библиотека имеет множество простых в использовании функций для составления обещаний любым мыслимым образом, заботясь обо всех низкоуровневых вещах, с которыми вы не хотите иметь дело.Если вы обнаружили необходимость составить некоторые обещания по-новому, которые не поддерживаются существующей вспомогательной функцией, то ваша последняя функция с неизбежными отложенными значениями должна быть вашей последней опцией. Подумайте о переходе на более содержательную библиотеку и / или сообщите об ошибке в вашей текущей библиотеке. Его сопровождающий должен иметь возможность извлекать композицию из существующих функций, реализовывать для вас новую вспомогательную функцию и / или помогать определять крайние случаи, которые необходимо обработать.
источник
setTimeout
, в которых можно использовать конструктор, но его не следует рассматривать как «обещание конструктора anitpattern»?setTimeout
», но « функцияsetTimeout
сама по себе ».setTimeout
», а« сама функцияsetTimeout
»» Можете описать, связать различия между ними?setTimeout
явно отличается от функцииsetTimeout
самого , не так ли?