Это "Отсроченный антипаттерн"?

Мне трудно понять "отсроченный антипаттерн". Я думаю, что я понимаю это в принципе, но я не видел супер простого примера того, что служба, с разным обещанием и с антипаттерном, поэтому я решил, что попытаюсь сделать свой собственный, но посмотрю, как я не супер в знании об этом, я сначала получу разъяснение.

У меня есть ниже в 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
        });
    }