Alex Rivera | Logout

Processing $http response in service

Asked 2012-09-20T03:36:10.003
233

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

Edit
Report

3 Answers

58

Because it is asynchronous, the $scope is getting the data before the ajax call is complete.

You could use $q in your service to create promise and give it back to controller, and controller obtain the result within then() call against promise.

In your service,

app.factory('myService', function($http, $q) {
  var deffered = $q.defer();
  var data = [];  
  var myService = {};

  myService.async = function() {
    $http.get('test.json')
    .success(function (d) {
      data = d;
      console.log(d);
      deffered.resolve();
    });
    return deffered.promise;
  };
  myService.data = function() { return data; };

  return myService;
});

Then, in your controller:

app.controller('MainCtrl', function( myService,$scope) {
  myService.async().then(function() {
    $scope.data = myService.data();
  });
});
answered 2012-09-20T05:35:40.227
4

When binding the UI to your array you'll want to make sure you update that same array directly by setting the length to 0 and pushing the data into the array.

Instead of this (which set a different array reference to data which your UI won't know about):

 myService.async = function() {
    $http.get('test.json')
    .success(function (d) {
      data = d;
    });
  };

try this:

 myService.async = function() {
    $http.get('test.json')
    .success(function (d) {
      data.length = 0;
      for(var i = 0; i < d.length; i++){
        data.push(d[i]);
      }
    });
  };

Here is a fiddle that shows the difference between setting a new array vs emptying and adding to an existing one. I couldn't get your plnkr working but hopefully this works for you!

answered 2012-09-20T04:47:55.007
4

Related to this I went through a similar problem, but not with get or post made by Angular but with an extension made by a 3rd party (in my case Chrome Extension).
The problem that I faced is that the Chrome Extension won't return then() so I was unable to do it the way in the solution above but the result is still Asynchronous.
So my solution is to create a service and to proceed to a callback

app.service('cookieInfoService', function() {
    this.getInfo = function(callback) {
        var model = {};
        chrome.cookies.get({url:serverUrl, name:'userId'}, function (response) {
            model.response= response;
            callback(model);
        });
    };
});

Then in my controller

app.controller("MyCtrl", function ($scope, cookieInfoService) {
    cookieInfoService.getInfo(function (info) {
        console.log(info);
    });
});

Hope this can help others getting the same issue.

answered 2013-06-23T11:52:46.583

Your Answer