Abstracting $http calls into service

旧街凉风 提交于 2020-02-03 08:15:12

问题


I'm wondering what the best way to abstract $http calls into an angularjs service is. I've done a bit of research and this seems to be the most common way:

app.factory('myService', function($http) {
 return {
   getFoo: function() {
     return $http.get('foo.json').then(function(result) {
       return result.data;
     });
   }
 }
});

app.controller('MainCtrl', function($scope, myService) {
  //the clean and simple way
  $scope.foo = myService.getFoo();
}

But the problem with this approach is I can't figure out how to do anything on .error.

I'd prefer to have my .success and .error callbacks inside my controller.

Is there a way to abstract the http call inside the service whilst maintaining .error and .success callbacks inside the controller?

Thank you.


回答1:


You can still use the on success/error calls.

The method you've highlighted returns a "Promise" object. A good thing about promises is that they are chainable.

So say you wish to respond to a $http request error in your controller:

app.factory('myService', function($http) {
 return {
   getFoo: function() {
     return $http.get('foo.json').then(function(result) {
       return result.data;
     });
   }
 }
});

app.controller('MainCtrl', function($scope, myService) {
  //the clean and simple way
  $scope.foo = myService.getFoo().then(function(){
    //Do something with successful response
  }, function(){
    //Do something with unsuccessful response
  });
}

NOTE: This following next section no longer holds true. Promises used in templates are no longer automatically resolved to its values when the promise resolves.

You should also understand why assigning $scope.foo works in your templates. AngularJS has a bit of magic that will resolve any promises to the object you need in a template. So while your template might reference foo.bar and the output will be correct, whats actually happening in the background is that the template is waiting for the promise to be fulfilled before rendering that part of the template.

Also, another gotcha is to remember to return an rejected promise if you're handling the error somewhere up in the chain.

For example:

app.factory('myService', function($http, $q) {
 return {
   getFoo: function() {
     return $http.get('foo.json').then(function(result) {
       return result.data;
     }, function(result){
      //I'm doing something here to handle the error
      return $q.reject(result);
     });
   }
 }
});

app.controller('MainCtrl', function($scope, myService) {
  //the clean and simple way
  $scope.foo = myService.getFoo().then(function(){
    //Do something with successful response
  }, function(){
    //Do something with unsuccessful response
  });
}

If we didn't return a rejected promise in the service, the controller's 'success' code path will be run instead of the reject path.



来源:https://stackoverflow.com/questions/17913956/abstracting-http-calls-into-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!