Dave
Dave

Reputation: 4048

angularjs chain http post sequentially

In my application, I am storing data in local storage and trigger async http post in the background. Once successfully posted, the posted data gets removed from local storage. When http post is in process, there may be more data added to local storage so I need to queue up the post and sequentially process it because, I need to wait for the local storage to be cleared from the successful posts. The task should be called recursively until there is data in local storage.

taskQueue: function () {
    var deferred = $q.defer();
    queue.push(deferred);
    var promise = deferred.promise;

    if (!saveInProgress) {
      // get post data from storage
      var promises = queue.map(function(){$http.post(<post url>, <post data>).then(function(result){
          // clear successful data
          deferred.resolve(result);
      }, function(error){
         deferred.reject(error);
      })
    })

    return $q.all(promises);
}

As angular newbie, I am having problems with the above code not being sequential. How can I achieve what I intend to? The queue length is unknown and also the queue length increases as the process is in progress. Please point me to other answers if this is a duplicate.

Upvotes: 3

Views: 3195

Answers (3)

jusopi
jusopi

Reputation: 6813

While having a library solution would be great (per @nstoitsev's answer), you can do this without it.

sequential requests of unknown length

Just to recap:

  • we do not know the number of requests
  • each response may enqueue another request

A few assumptions:

  • all requests will be working on a common data object (local storage in your case)
  • all requests are promises

running the queue

function postMyData (data){
    return $http.post(<url>, data)
}

var rqsts = []

function executeQueue (){

    if(!rqsts.length)
         //we're done
         return

    var rqst = rqsts.shift()        
    rqst()
    .then(function(rsp){
        //based on how you're determining if you need to do another request...  
        if(keepGoing)
            rqsts.push(postMyData(<more data>))           
    })
}
 

codepen - http://codepen.io/jusopi/pen/VaYRXR?editors=1010

I intentionally left this vague because I don't understand what the conditions for failure are and if you wanted to vary up the requests to use more than the same $http.post call, you could pass it back in some way.

and just a suggestion

As angular newbie...

Many things are progressing towards this whole functional, reactive programming paradigm. Since you're relatively new to Angular and NG2 already has some of this built in, it might be worthy of your attention. I think rxjs is already in many NG2 example bundles.

Upvotes: 2

danday74
danday74

Reputation: 56956

Async.js sounds a good idea but if you don't want to use a library ...

$q.all will batch up an array of requests and fire them at the same time and will resolve when ALL promises in the array resolve - WHICH IS NOT WHAT YOU WANT.

to make $http calls SEQUENTIALLY from an array do this ....

var request0 = $http.get('/my/path0');
var request1 = $http.post('/my/path1', {data:'fred'});
var request2 = $http.get('/my/path2');
var requestArray = [];

then ...

requestArray.push(request0);
requestArray.push(request1);
requestArray.push(request2);

then ...

requestArray[0].then(function(response0) {
    // do something with response0
    return requestArray[1];
}).then(function(response1) {
    // do something with response1
    return requestArray[2];
}).then(function(response2) {
    // do something with response2
}).catch(function(failedResponse) {
    console.log("i will be displayed when a request fails (if ever)", failedResponse)
});

Upvotes: 3

nstoitsev
nstoitsev

Reputation: 946

The easies way to achieve this is by using Async.js. There you can find a method called mapSeries. You can run it over the queue and it will sequentially process all elements of the array one by one, and will continue to the next element only when the correct callback is called.

Upvotes: 1

Related Questions