Is this a “Deferred Antipattern”?

后端 未结 3 1448
日久生厌
日久生厌 2020-11-21 06:25

I\'m finding it hard to understand the \"deferred antipattern\". I think I understand it in principal but I haven\'t seen a super simple example of what a service, with a di

相关标签:
3条回答
  • 2020-11-21 07:00

    I would say that it is the classic deferred anti-pattern because you are creating needless deferred objects. However, you are adding some value to the chain (with your validation). Typically, IMO, the anti-pattern is particularly bad when deferred objects are created for very little or no benefit.

    So, the code could be much simpler.

    $q promises have a little documented feature of automatically wrapping anything returned inside a promise in a promise (using $q.when). In most cases this means that you shouldn't have to manually create a deferred:

    var deferred = $q.defer();
    

    However, that is how the documentation demonstrates how to use promises with $q.

    So, you can change your code to this:

    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
            });
        }
    
    0 讨论(0)
  • 2020-11-21 07:02

    Using the $q constructor is a deferred anti-pattern

    ANTI-PATTERN

    vm.download = function() {
      var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";    
      return $q(function(resolve, reject) {    
        var req = {
          method: 'POST',
          url: url,
          responseType: 'arraybuffer'
        };   
        $http(req).then(function(response) {
          resolve(response.data);
        }, function(error) {
          reject(error);
        });
      });
    }
    

    CORRECT

    vm.download = function() {
        var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";    
        var req = {
          method: 'POST',
          url: url,
          responseType: 'arraybuffer'
        };   
        return $http(req).then(function(response) {
            return response.data;
        });
    }
    

    The $http service already returns a promise. Using the $q constructor is unnecessary and error prone.

    0 讨论(0)
  • 2020-11-21 07:09

    Is this a “Deferred Antipattern”?

    Yes, it is. 'Deferred anti-pattern' happens when a new redundant deferred object is created to be resolved from inside a promise chain. In your case you are using $q to return a promise for something that implicitly returns a promise. You already have a Promise object($http service itself returns a promise), so you just need to return it!

    Here's the super simple example of what a service, with a deferred promise and one with antipattern look like,

    This is anti-pattern

    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;
            }
         }
    }])
    

    This is what you should do

    app.factory("SomeFactory",['$http']){
        return {
            getData: function(){
               //$http itself returns a promise 
                return $http.get(destinationFactory.url);
            }
    }
    

    while both of them are consumed in the same way.

    this.var = SomeFactory.getData()
        .then(function(response) {
            //some variable = response;
        },function(response) {
            //Do error handling here
    });
    

    There's nothing wrong with either examples(atleast syntactically)..but first one is redundant..and not needed!

    Hope it helps :)

    0 讨论(0)
提交回复
热议问题