質問

what's the best way to declare a service I found this 2 different ways i can't seem to see the difference: first method:

angular.module('app', [])
   .factory('Data', ['$http',function($http){
     return {
         get: function(fileName,callback){
              $http.get(fileName).
              success(function(data, status) {
                  callback(data);
              });
         }
     };
   }]);

second method:

angular.module('app', [])
   .factory('Data', ['$http', function($http){
     var Url   = "data.json";
     var Data = $http.get(Url).then(function(response){
       return response.data;
     });
     return Data;
   }]);

Which one is better and why? Thanks in advance.

役に立ちましたか?

解決

There are a few things to separate out here.

Object vs Promise

Services are singletons, so in the second method (returning just the promise) your data will never be updated again. That's often the desired result. In your first method, it will be called fresh every time (though $http has a cache option).

From my perspective, one would only return a service object if there were multiple methods (e.g. get, create, delete, etc.) or it needed to be called multiple times. Otherwise, we're just piling on cruft.

Promise vs Callback

Promises are awesome - we should be leveraging them. Passing in a callback is nice, but it's also very limiting. With promises, we can easily chain them together, e.g.:

Data.get()
.then( massageDataFn )
.then( secondMassageFn )
.then(function ( data ) {
  $scope.items = data;
});

Besides, $http already returns a promise. Why throw that away?

Method Parameters

Your former (object method) took in some parameters. While I am wary of a controller passing in an URL, there are some cases where it's desirable. But you can do this by just returning a function rather than an object:

.factory( 'Data', [ '$http', function ( $http ) {
  return function ( fileName, callback ) {
    // $http call here...
  };
}]);

And then only the consideration is Object vs Promise, discussed above.

Conclusion

If your service has an API, return an object with public API methods, where each of those methods returns a promise. If your service is just to get some data once, just return the promise and be done with it.

他のヒント

The latter requires foreknowledge of the url and the callback function. The latter allows you to set both the target url and the callback, which is far more flexible. I would suggest going with the former in most cases, but it really depends on what you are trying to do.

The first sample makes the asynchrony of the HTTP request explicit for the service user, which is preferable, I think, to handing the service user a promise object (which is what "Data" is in the second sample) and letting the user proceed with its imperative operations, perhaps depending on a "Data" object that hasn't been filled in yet.

Your second method is a little more verbose, but one major benefit is the ability to create private properties / methods, and only return the public object.

Note that this should be planned around with regards to testing etc - from personal experience with Angular, private methods and properties are more difficult to unit test etc.

As an example:

angular.module('app', [])
   .factory('Data', ['$http', function($http){
        var private = {
            property: 100,
            method: function(data) {
                return data * 2;
            }
        };
        var public = {
            property: true,
            property_two: false,
            method: function(data) {
                return private.method(data + private.property);
            }
        };
        return public;
   }]);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top