Что такое явный антипаттерн конструкции обещания и как его избежать?
я писал код, который делает что-то похожее:
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 антиобразец конструктор" соответственно, что плохого в этом коде, и почему это называется антиобразец?
2 ответов:
The отложенный антипаттерн (теперь явное построение анти-паттерна) придумал Esailija это общий анти-шаблон люди, которые являются новыми для обещаний сделать, я сделал это сам, когда я впервые использовал обещания. Проблема с приведенным выше кодом заключается в том, что он не использует тот факт, что обещает цепочку.
обещания могут связываться с
.thenи вы можете вернуть обещания напрямую. Ваш код вgetStuffDoneможно переписать так:function getStuffDone(param){ return myPromiseFn(param+1); // much nicer, right? }обещания все о том, чтобы сделать асинхронный код более читаемым и вести себя как синхронный код, не скрывая этого факта. Обещания представляют собой абстракцию над значением одной временной операции, они абстрагируют понятие оператора или выражения в языке программирования.
вы должны использовать только отложенные объекты, когда вы преобразование API в обещания и не может сделать это автоматически, или когда вы пишете функции агрегации, которые проще выражаются таким образом.
Цитирую Esailija:
Это самый распространенный анти-паттерн. Легко попасть в это, когда вы действительно не понимаете обещаний и думаете о них как о прославленных источниках событий или утилите обратного вызова. Давайте повторим: обещания о том, чтобы асинхронный код сохранил большинство потерянных свойств синхронного кода, таких как плоский отступ и один канал исключения.
что с ним не так?
но схема работает!
Повезло тебе. К сожалению, это, вероятно, не так, как вы, вероятно, забыли какой-то крайний случай. В более чем половине случаев, которые я видел, автор забыл позаботиться о обработчике ошибок:
return new Promise(function(resolve) { getOtherPromise().then(function(result) { resolve(result.property.example); }); })если другое обещание будет отклонено, это произойдет незаметно вместо того, чтобы распространяться на новое обещание (где оно будет обработано) - и новое обещание остается навсегда в ожидании,что может вызвать утечки.
то же самое происходит в случае, если ваш код обратного вызова вызывает ошибку - например, когда
resultнетpropertyи исключение. Это было бы необработанным и оставило бы новое обещание нерешенным.напротив, используя
.then()автоматически заботится об обоих этих сценариях и отклоняет новое обещание, когда происходит ошибка:return getOtherPromise().then(function(result) { return result.property.example; })отложенный антипаттерн не только громоздкий, но и ошибки. Используя
.then()для цепочки гораздо безопаснее.но я все уладил!
в самом деле? Хороший. Тем не менее, это будет довольно подробно и обильно, особенно если вы используете библиотеку обещаний, которая поддерживает другие функции, такие как отмена или передача сообщений. Или, может быть, это будет в будущем, или вы хотите поменять свою библиотеку на лучшую? Вы не захотите переписывать свой код для что.
методы библиотек (
then) не только поддерживает все функции, они также могут иметь определенные оптимизация на месте. Использование их, скорее всего, сделает ваш код быстрее или, по крайней мере, позволит оптимизировать будущие версии библиотеки.как мне этого избежать?
поэтому всякий раз, когда вы обнаружите, что вручную создаете
Promiseили и уже существующие обещания, сначала проверьте API библиотеки. Этот Отложенный антипаттерн часто применяется людьми, которые видят обещания [только] как образец наблюдателя - но обещания больше чем обратных вызовов: они должны быть составные. Каждая приличная библиотека имеет множество простых в использовании функций для составления обещаний всеми мыслимыми способами, заботясь обо всех низкоуровневых вещах, с которыми вы не хотите иметь дело.если вы нашли необходимость составить некоторые обещания по-новому, что не поддерживается существующая вспомогательная функция, написание собственной функции с неизбежными отсрочками должно быть вашим последним вариантом. Рассмотрите возможность переключения на более функциональную библиотеку и / или файл ошибки против вашей текущей библиотеки. Его сопровождающий должен быть в состоянии вывести композицию из существующих функций, реализовать новую вспомогательную функцию для вас и/или помочь определить крайние случаи, которые необходимо обработать.
Comments