Bastien Vandamme
Bastien Vandamme

Reputation: 18465

Queue Ajax request in Javascript?

I would like to execute an Ajax request every seconds. My next code work perfectly.

    window.onload = function () {
        setTimeout(doStuff, 1000); //wait before continuing
    }

    function doStuff() {
        $.ajax({
            // ...
        });
        setTimeout(doStuff, 1000);
    };

But at this moment if I use a tool like Fiddler to block my request the system continues to send new Ajax request. I would like to queue them and send my next Ajax request only after the answer of my server. How can I do that ?

Upvotes: 1

Views: 1682

Answers (5)

Klik
Klik

Reputation: 1776

I just ran into a similar problem and solved it, so I thought I would share my answer on SO.

Here is what I did:

//Global vars:

var ajaxQue = [];   //array containing immediate que of ajax object request to be fired off
var ajaxCache = {}; //object holding ajax requests. 
var ajaxThreadActive = 0;   //var for indicating if the ajaxQue if currently firing off or not. 



//get the last (newest) ajax Request
function getLastRequest() {
    for (i in ajaxCache) {
        ajaxQue.push(ajaxCache[i]);
        delete ajaxCache[i];
        return; //aim to only get one request at a time inorder to catch more requests
    }
    //if no items in the cache exist, will come here
    ajaxThreadActive = 0; //ajax queue is now empty
}

//put an ajax request in an obj with a specific id so that if a newer ajax request is created before the ajax requests are finished sending, it will replace the old one
function queRequest(ajaxObj, id) {
    if (arguments.length != 2) {    //id argument is optional
        id = uuid++;    //create unique id as default
    }
    if (id in ajaxCache) {
        console.log('duplicate request');   
    }
    ajaxCache[id] = ajaxObj;
    if (ajaxThreadActive == 0) {
        ajaxThreadActive = 1;
        getLastRequest();   //retrieve most 'updated' ajax request
        fireOffAjaxQue();   
    } else {
        return 'ajax thread is running';
    }
}


//fire off the ajax queue
function fireOffAjaxQue () {
    if ((ajaxQue.length > 0) && ajaxThreadActive == 1) {    //an if check on the thread active incase I want to close this from another place in code
        $.ajax(ajaxQue[0]).always( function () {
            setTimeout(function () {
                getLastRequest();   //retrieve most 'updated' ajax request
                fireOffAjaxQue();
            }, 50); //fire off another ajax request since this one has been completed.
        });
        ajaxQue.shift();    //perform this immediately after the ajax request is sent, will execute before the .always() function
    } 
}

Usage is simple, instead of what you normally do in jQuery:

$.ajax({url: 'someplace.php',
        data: dataVar,
        success: function(data) {...});

Change it with this:

//create ajax object
var ajaxObj = {url: 'someplace.php',
               data: dataVar,
               success: function (data) {...}};
 //send ajax object to que

Then send it to the Que with this:

 queRequest(ajaxObj);  //send to que without an id since this is a unique request
 // *******OR********
 queRequest(ajaxObj, id);   //send to the que with an id IF this is to replace any 'older' requests of the same id

I have included an AjaxCache to hold the newest ajax requests. I.e. if you have a function that sends repeated requests on a user's keystroke, sometimes you only need to send the latest, most up-to-date request (like form information). In the way this manager is made, it handles the requests to have associated ids (optional) so that a new request can replace an old request by overwriting the request with the same id.

//for an example, I use it like this in my webpage
queRequest(ajaxObj, 'table1Data'); 

Now, in case the queue is still firing off any requests I make with 'table1Data' will only overwrite the ajaxObj with id 'table1Data' and thus send only the minimal amount of Ajax requests.

Upvotes: 1

Sirko
Sirko

Reputation: 74076

Just move the trigger for the next request in the success handler of the request before:

function doStuff() {
    $.ajax({
        // ...
        success: function( data ) {
           // your other code
           setTimeout(doStuff, 1000);
        }
    });  
};

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1039060

Call the setTimeout inside the success callback:

function doStuff() {
    $.ajax({
        // ...
        success: function(result) {
            // ...
            setTimeout(doStuff, 1000);
        }
    });
}

Upvotes: 2

Samba
Samba

Reputation: 605

I have used : http://code.google.com/p/jquery-ajaxq/ for a production application.

I have customized the code to do abort of running ajax request.

  • Navigational Ajax (navigating to screen) - used abort.

  • Data submit - used queue. Can have different queues with different names.

Upvotes: 0

Brandon Ferrara
Brandon Ferrara

Reputation: 1388

use async to make ajax requests wait until one completes first

jQuery.ajax({
    url: "query.php?Time="+myTimestamp(),
    async: false,
    success: function(data){
        jQuery.ajax({
            url: "query.php?Time="+myTimestamp(), 
            async: false,
            success: function(data){

            }
        });
    }
});

Upvotes: 0

Related Questions