1

I have this fiddle example, in which I'm making three consecutive calls to a service function (emulating $http Request interceptor function) returning a promise, the code is below. I want the second and next calls to wait until the previous finishes, because the second and next ones depend on the previous response. currently Im getting

Message 1: The value returned is 6000,

Message 2: The value returned is 600

Message 3: The value returned is 30

but I want to get

Message 1: The value returned is 10

Message 2: The value returned is 200

Message 3: The value returned is 6000

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

myApp.factory('interceptor',['$q','$timeout',function($q,$timeout){
  var _fact ={};
  var asynTimeout;
  var _intvalue = 1;
  var _asyncTask = function(time, value){
     var deferred = $q.defer();

     asynTimeout = $timeout(function(){
          _intvalue = _intvalue*value
          deferred.resolve(_intvalue);},time)


    return deferred.promise;
};

  _fact.asyncTask = _asyncTask;
  return _fact;
}]);

myApp.controller('AppCtrl',['$scope', 'interceptor',function ($scope,interceptor) {

    interceptor.asyncTask(1500, 10).then(function(returnedval){
     $scope.message1  = "The value returned is " + returnedval;});   

    interceptor.asyncTask(1000, 20).then(function(returnedval){
     $scope.message2  = "The value returned is " + returnedval;});

    interceptor.asyncTask(800, 30).then(function(returnedval){
     $scope.message3  = "The value returned is " + returnedval;});

 }])

the template would be:

 <div ng-controller="AppCtrl">
   <div>Message 1: {{message1}}</div>
   <div>Message 2: {{message2}}</div>
   <div>Message 3: {{message3}}</div>
 </div> 

Notice, the solution should be implemented in the factory function -nested calls at controller is not a solution for this scenario-, what I want is something as follow at interceptor side

myApp.factory('interceptor',['$q','$timeout',function($q,$timeout){
   ...

  var _asyncTask = function(time, value){
     var deferred = $q.defer();

   ***IF ITS RUNNING A PREVIOUS CALL WAIT FINISHES AND THEN(function(){***
       asynTimeout = $timeout(function(){
          _intvalue = _intvalue*value
          deferred.resolve(_intvalue);},time)
   ***}**
    return deferred.promise;
  };

  ...

  return _fact;
}]);

3 Answers 3

1

Give this a try. Stash away the promise from the previous $timeout and use it to wait for previous operations to complete. Also simplified it a bit, removing the deferred and using $timeout's promise instead...

myApp.factory('interceptor', ['$q', '$timeout', function ($q, $timeout) {
    var _fact = {};
    var _intvalue = 1;
    var waitPromise = $q.when(true);

    var _asyncTask = function (time, value) {
        waitPromise = waitPromise.then(function () {
            return $timeout(function () {
                _intvalue = _intvalue * value;
                return _intvalue;
            }, time);
        });
        return waitPromise;
    };

    _fact.asyncTask = _asyncTask;
    return _fact;
}]);

Fiddle

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

1 Comment

Perfect, just what i was looking for
1

You can create a queue of promises in the factory. Something like this:

myApp.factory('interceptor',['$q','$timeout',function($q,$timeout){
    var _fact ={};
    var asynTimeout;
    var queue = $q.when();
    var _intvalue = 1;
    var _asyncTask = function(time, value){
        queue = queue.then(
            function () {
                var deferred = $q.defer();
                asynTimeout = $timeout(function(){
                   _intvalue = _intvalue*value
                   deferred.resolve(_intvalue);
                },time)
                return deferred.promise;
            }
        )
        return queue;
    };
    _fact.asyncTask = _asyncTask;
    return _fact;
}]);

Comments

0

Does the order of showing message 1,2,3 matter? If not, you can nest asyncTask, see jsfiddle.net/1k6Lswab/8/

2 Comments

As I mentioned before, nested async task calls at controller side is not a solution for this scenario.
ah, I missed the last part of your post:)

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.