Это "Отсроченный антипаттерн"?
Мне трудно понять "отсроченный антипаттерн". Я думаю, что я понимаю это в принципе, но я не видел супер простого примера того, что служба, с разным обещанием и с антипаттерном, поэтому я решил, что попытаюсь сделать свой собственный, но посмотрю, как я не супер в знании об этом, я сначала получу разъяснение.
У меня есть ниже в factory (SomeFactory):
//url = 'data.json';
return {
getData: function(){
var deferred = $q.defer();
$http.get(destinationFactory.url)
.then(function (response) {
if (typeof response.data === 'object') {
deferred.resolve(response.data);
} else {
return deferred.reject(response.data);
}
})
.catch(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
Причина, по которой я проверяю его объект, - это просто добавить простой уровень проверки на $http.get()
И ниже, в моей директиве:
this.var = SomeFactory.getData()
.then(function(response) {
//some variable = response;
})
.catch(function(response) {
//Do error handling here
});
Теперь, к моему неуверенности, это антипаттерн. Потому что оригинальное отложенное обещание ловит ошибку и просто проглатывает ее. Он не возвращает ошибку, поэтому, когда вызывается этот метод getData, я делаю еще один улов, чтобы захватить ошибку.
Если это НЕ антипаттерн, может ли кто-нибудь объяснить, почему оба требуют "обратного вызова"? Когда я впервые начал писать эту директиву factory/, я ожидал, что буду делать обещанное обещание где-нибудь, но я не ожидал, что должен быть .catch()
с обеих сторон (иначе я думал, что могу получить factory верните ответ или ошибку, если я сделал SomeFactory.getData()
Ответы
Ответ 1
Является ли это "отложенным антипаттерном"?
Да, это так. "Отложенный анти-шаблон" происходит, когда создается новый избыточный отложенный объект, который должен быть разрешен изнутри цепочки обещаний. В вашем случае вы используете $q, чтобы вернуть обещание для чего-то, что неявно возвращает обещание. У вас уже есть объект Promise ($http service
сам возвращает promise
), поэтому вам просто нужно его вернуть!
Вот супер простой пример того, как выглядит сервис с отложенным обещанием и с антипаттерном,
Это анти-шаблон
app.factory("SomeFactory",['$http','$q']){
return {
getData: function(){
var deferred = $q.defer();
$http.get(destinationFactory.url)
.then(function (response) {
deferred.resolve(response.data);
})
.catch(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
}
}])
Это то, что вы должны делать
app.factory("SomeFactory",['$http']){
return {
getData: function(){
//$http itself returns a promise
return $http.get(destinationFactory.url);
}
}
в то время как оба они потребляются одинаково.
this.var = SomeFactory.getData()
.then(function(response) {
//some variable = response;
},function(response) {
//Do error handling here
});
Нет ничего плохого в обоих примерах (по крайней мере синтаксически).. но первый из них избыточен и не нужен!
Надеюсь, это поможет:)
Ответ 2
Я бы сказал, что это классический отложенный анти-шаблон, потому что вы создаете ненужные отложенные объекты. Однако вы добавляете некоторое значение в цепочку (с вашей проверкой). Как правило, IMO, анти-шаблон особенно плохо, когда отложенные объекты создаются очень мало или вообще не приносят пользы.
Таким образом, код может быть намного проще.
$q
promises имеют небольшую задокументированную функцию автоматического переноса чего-либо, возвращаемого в обещание в обещании (используя $q.when
). В большинстве случаев это означает, что вам не нужно вручную создавать отложенные:
var deferred = $q.defer();
Однако, как документация демонстрирует, как использовать promises с $q
.
Итак, вы можете изменить свой код на это:
return {
getData: function(){
return $http.get(destinationFactory.url)
.then(function (response) {
if (typeof response.data === 'object') {
return response.data;
} else {
throw new Error('Error message here');
}
});
// no need to catch and just re-throw
});
}