8

I have a service where I am pulling data from server. When I click the button to send out the request to server through this service, the window freezes until I receive a response from server. Is there anything I can do to make this request asynchronous ?

Here is my service.

app.factory('service', function($http) {
  return {
    getLogData : function(startTime,endTime){
      return $http({
        url:     baseURL + 'getLogData',
        method:  'GET',
        async:   true,
        cache:   false,
        headers: {'Accept': 'application/json', 'Pragma': 'no-cache'},
        params:  {'startTime': startTime , 'endTime': endTime}
      });
    }
  };
)};

HTML.

<button ng-click="getData()">Refresh</button>
<img src="pending.gif" ng-show="dataPending" />

Code

$scope.getData = function(){
  service.getLogData().success(function(data){
    //process data
  }).error(function(e){
    //show error message
  });
}
3
  • Ajax calls shouldn't be synchronous. In face you don't even need async: true option. Can you explain more about how your window freeze? Like everything is not clickable, not responding? Commented Sep 27, 2013 at 16:41
  • Do you have a lot of data being returned? The call shouldn't block during the ajax call, but I imagine it could block if it returns a lot of data and the "process data" code is perhaps slow. Commented Sep 27, 2013 at 16:44
  • Everything is not clickable. I don't have much data but it takes long time to get. Also I am using ng-grid to present it. Commented Sep 27, 2013 at 17:09

4 Answers 4

13

While there is some argument about the pros and cons of your approach, I am thinking that the problem is answered here: AJAX call freezes browser for a bit while it gets response and executes success

To test if this in fact part of the problem, dummy up a response and serve it statically. I use Fiddler or WireShark to get the response and then save to a file like testService.json. XHR and all of it's various derivatives like $HTTP $.ajax see it as a service though the headers might be slightly different.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. This was indeed the solution. Nothing wrong with Angular. I used the self executing function.
3

Use the success promise, and wrap up the log data in a set of objects that you can attach to a $scope.

So instead of having your service have a blocking method, have it maintain a list of "LogEntries".

   // constructor function
   var LogEntry = function() {
      /*...*/
   }

   var logEntries = [];

   // Non-blocking fetch log data
   var getLogData = function() {
        return $http({
            url : baseURL + 'getLogData',
            method : 'GET',
            async : true,
            cache : false,
            headers : { 'Accept' : 'application/json' , 'Pragma':'no-cache'},
            params : {'startTime' : startTime , 'endTime' : endTime}
        }).success(function(data) {;
           // for each log entry in data, populate logEntries
           // push(new LogEntry( stuff from data ))...
        };
   } 

Then in your controller, inject your service and reference this service's log data array so Angular will watch it and change the view correctly

   $scope.logEntries = mySvc.logEntries;

Then in the HTML, simply do something over logEntries:

  <p ng-repeat="logEntry in logEntries">
    {{logEntry}}
  </p>

9 Comments

$http returns a promise, so while I agree that the service should encapsulate the response into some sort of object, I don't believe his method should be blocking. I'm wondering if instead the issue is the ajax call is returning a huge amount of data and the processing code is freezing everything up.
Assign $http promise to view is not a good idea, see here github.com/angular/angular.js/issues/3196
@Daiwei - but he's not assigning the promise to the view. The returned promise is being resolved in the controller and the data processed there. It isn't being assigned.
The data isn't huge. Only 30 rows and 6 columns. I thought its the ng-grid but as soon as it received data, it parsed immediately.
$scope.logEntries = mySvc.logEntries; Isn't that a one time call. I need to get log based on different start and end times.
|
2

use this code to config

$httpProvider.useApplyAsync(true);

Comments

0
var url = //Your URL;

  var config = {
    async:true
  };

  var promise= $http.get(url, config);
     promise.then(
     function (result) 
     {
       return result.data;
     },
     function (error) 
     {
       return error;
     }
    );

2 Comments

Please edit to explain how this helps to answer the user's question.
All are the above shown angular syntax were old/wrong, so my intesion was to update them. Above code is to make async service call, however if data is huge, you can not do much at client side only.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.