Phate
Phate

Reputation: 6612

Asynchronous call: call a function upon receiving first "pending" response by server

I have an asynchronous web service which will return status "pending" immediately until it returns either 200 or an error. This is my code so far:

        $http.get('/myweb/services/callService').success(function(response, status, headers, config){
            ...handling success

        }).error(function(err, status, headers, config){
            //handling failure
        });

        //called just after $http.get
        $scope.askProgress();

Where askProgress is:

$http.get('/myweb/services/progress').success(function(response, status, headers, config){
        console.log(response);
        $scope.reportProgress = response.description;

        if(response.description < 100){//description is a 0-100 value indicating progress
            ...updating status...
            $timeout(function() {$scope.askProgress();}, 1000); //calling again
        }else{
            $scope.reportProgressL = "Done!";
        }
    }).error(function(err, status, headers, config){
        alert('Error: '+err+" "+status);
    });

My problem is that the first call to askProgress is made before the service returns status "pending" leading to a non consistent progress value. I'd like for the askProgress function to be called just after the service gives me the first "pending"...is it possible?

Upvotes: 0

Views: 283

Answers (1)

Matt Herbstritt
Matt Herbstritt

Reputation: 4862

Not sure I understand you problem fully but it sounds like you need to be calling your askProgress() function after the first http request returns. If so, have you tried putting the call inside your then() call?

$http
    .get('/myweb/services/callService')
    .then(function(response, status, headers, config){
        return $scope.askProgress();
    })
    .then(function(progressResponse){

    })
    .catch(function(error){});

Update

I think you will need to register an $http interceptor to track the state of your request.

Try this:

DEMO

app.js

var app = angular.module('plunker', []);

app.factory('myHttpInterceptor', [ function() {

    var pendingRequests = {};

    return {

      getPendingRequests: function(){
        return pendingRequests;
      },

      request: function(request) {
        console.log('*** request made @ %s ***', new Date());
        pendingRequests[request.url] = true;
        console.log('pendingRequests', pendingRequests);
        console.log('**************************');
        return request;
      },

      response: function(response) {

        console.log('*** response received @ %s ***', new Date());

        var url = response.config.url;

        if(pendingRequests.hasOwnProperty(url)){
          delete pendingRequests[url];
        }

        console.log('pendingRequests', pendingRequests);
        console.log('**************************');

        return response;
      }

    };

}]);

app.config(['$httpProvider', function($httpProvider) {

  // register our factory as an http interceptor
  // in the config phase
  $httpProvider.interceptors.push('myHttpInterceptor');

}]);

app.controller('MainCtrl', function($scope, $http, $timeout, myHttpInterceptor) {

  var targetUrl = 'big-data.json';


  $scope.callService = function(){

    console.log('*** call service ***');

    return $http.get(targetUrl)
      .then(function(){
        console.log('********** done, success **********');
      })
      .catch(function(){
        console.log('********** done, error **********'); 
      });

  }

  $scope.askProgress = function(){

    var pendingReqs = myHttpInterceptor.getPendingRequests();


    // the request in this demo is very quick
    // so I have had to change the time between checks
    // you will probably want to change this for your
    // own app
    return $timeout(1)
      .then(function(){

        if(pendingReqs.hasOwnProperty(targetUrl)){
          console.log('*** stil pending ***');
          return $scope.askProgress();
        }
        console.log('*** no pending requests ***');
        $timeout.cancel();

      })

  }

  $scope.callService();  
  $scope.askProgress(); 


});

Upvotes: 1

Related Questions