Testing $ http calls to a service

I am wondering what is the best way to abstract the $ http calls into the angularjs service. I did some research, and this is apparently 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 that I cannot figure out how to do this on .error.

I would rather have my .success and .error callbacks inside my controller.

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

Thanks.

+4
source share
1 answer

You can still use calls on successful startup / errors.

The selected method returns a "Promise" object. The good thing about promises is that they cling.

So, say you want to respond to the 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. The next next section is no longer running. promises used in templates will no longer automatically be resolved to its values ​​when the promise is resolved.

You should also understand why the assignment of $scope.foo works in your templates. AngularJS has some magic that will allow any promises object you need in the template. Therefore, when your template can reference foo.bar and the output is correct, what happens in the background is that the template waits for the promise to be fulfilled before displaying this part of the template.

Also, another problem is remembering to return a rejected promise if you handle the error somewhere in the chain.

For instance:

 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 did not return the rejected promise in the service, instead of the rejection path, the controller's success code path will be executed.

+4
source

Source: https://habr.com/ru/post/1493980/


All Articles