Reputation: 681
I am working with the $http
in angularjs1.4.7.
I need to separate my controllers from any $http
requests. So i created a service as follows:
app.service('MyService', function($http, $q, $rootScope) {
this.getcustomers = function() {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'http://call/to/rest/api'
}).then(function successCallback(response) {
deferred.resolve(response.data);
}, function errorCallback(response) {
deferred.reject(error);
});
return deferred.promise;
};
});
Then in my controller i call that service as follows:
app.controller('registerationCtrl', ['$scope', '$http', 'MyService', '$location', function($scope, $http, MyService, $location) {
$scope.custlst = [];
$scope.getcustomers = function() {
var x = MyService.getcustomers().then(function(data) {
$scope.custlst = data;
}, function(err) {
alert(err);
});
}
}]);
Now, the above is not working it gives me a ReferenceError
of error now defined and points to the errorCallback
function in the service.
Question 1: What is wrong with the script?
Question 2: Is it important to use $q
? Keeping in mind that the server can be slow.
Thanks.
Upvotes: 1
Views: 5690
Reputation: 49590
As I mentioned in comments, the error you're seeing is due to the error
variable not being declared inside the errorCallback
function.
As for $q
- no need to use it, although the way you implemented would still work. To make it simpler and to follow the intent of promises (i.e. that they allow async code to mirror code composition of sync code) it's better to return the original promise of $http
(or of $http().then()
):
this.getcustomers = function() {
return $http({
method: 'GET',
url: 'http://call/to/rest/api'
})
// pre-process the HTTP response and return the data
.then(function(response) {
return response.data;
})
// If needed, create a custom error to hide HTTP details from caller
// otherwise, don't include .catch - the original error will "bubble up"
.catch(function(error) {
return $q.reject({
msg: "something broke"
});
});
};
Then, the client can be used as you intended:
MyService.getcustomers()
.then(function(data) {
$scope.customers = data;
})
.catch(function(error) {
console.log(error.msg);
})
Upvotes: 1
Reputation: 4874
Actually you don't need to use $q
to create a promise. $http
do it for you already, so you can simply do :
app.service('MyService', function($http) {
this.getcustomers = function() {
return $http.get({
method: 'GET',
url: 'http://call/to/rest/api'
});
};
});
Then you can chain your MyService.getcustomers
with .then()
easily and handle the response like that :
MyService.getcustomers.then(
function(data) {
//do something with data
},
function(error) {
//do something with error
}
);
I think you should take a look at this post I you want to better understand how promises works and behaves.
EDIT: update deprecated call to $http
.
Upvotes: 3
Reputation: 5571
Well, in the AngularJS docs: https://docs.angularjs.org/api/ng/service/$http
Deprecation Notice The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
You don't need to use the $q promise.
As you're using GET request, you might use the shortcut method to perform GET request.: $http.get();
.
So, you might try something like this:
MyService service: Only you need the $http
service.
app.service("MyService", ["$http", function ($http) {
this.getcustomers = function () {
return $http.get("http://call/to/rest/api");
};
}]);
The service above lets you use the service, in any controller. So, any controller can performs others action by using the same data.
registerationCtrl controller: You need the $scope
, MyService
and location
services.
app.controller("registerationCtrl", ["$scope", "MyService", "$location", function ($scope, MyService, location) {
$scope.custlst = [];
$scope.getcustomers = function () {
MyService.getcustomers().then(function (response) {
$scope.custlst = response.data;
}, function (err) {
alert(err);
});
};
}]);
}]);
Upvotes: 1