Processing $http response in service
I recently posted a detailed description of the issue I am facing here at SO. As I couldn't send an actual $http
request, I used timeout to simulate asynchronous behavior. Data binding from my model to view is working correct, with the help of @Gloopy
Now, when I use $http
instead of $timeout
(tested locally), I could see the asynchronous request was successful and data
is filled with json response in my service. But, my view is not updating.
updated Plunkr here
Solution 1:
Here is a Plunk that does what you want: http://plnkr.co/edit/TTlbSv?p=preview
The idea is that you work with promises directly and their "then" functions to manipulate and access the asynchronously returned responses.
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
Here is a slightly more complicated version that caches the request so you only make it first time (http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview):
app.factory('myService', function($http) {
var promise;
var myService = {
async: function() {
if ( !promise ) {
// $http returns a promise, which has a then function, which also returns a promise
promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
}
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = {};
};
$scope.getData = function() {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
};
});
Solution 2:
Let it be simple. It's as simple as
- Return
promise
in your service(no need to usethen
in service) - Use
then
in your controller
Demo. http://plnkr.co/edit/cbdG5p?p=preview
var app = angular.module('plunker', []);
app.factory('myService', function($http) {
return {
async: function() {
return $http.get('test.json'); //1. this returns promise
}
};
});
app.controller('MainCtrl', function( myService,$scope) {
myService.async().then(function(d) { //2. so you can use .then()
$scope.data = d;
});
});