简体   繁体   中英

Jquery - Multiple function calls to one AJAX call

I have a page that should load after the initial page load a bit of data trough AJAX that is then used in a few functions.

So far I can only get it to work with loading the AJAX requests separately (which means the same request is called like 30 times)

What I need is the possibility to have a function that can be called multiple times, but only activates the AJAX call once and the other times gives the data back without having again the same AJAX call that already gave the data back running (cause that's redundant and not needed, the data doesn't change).

Now I could do that by simply making a call and store it in a global variable and just check if something is in this variable or not...

BUT! The "but" is the problem, that these around 20 calls that need the information the AJAX delivers happen right after the DOM is loaded, right together with the AJAX call.

And so I cannot do that, because the 20 requests happen before the first AJAX call even finished showing all data.

I tried to do some stuff with JQueries "deferred", but could only manage to do it with one call and not with multiple calls at almost the same time without that it triggers the AJAX call everytime.

But I'm sure that must be possible somehow! Nicely, without some sort of loops and timeout. I really like the idea of loading pages and parts of pages partially. Input field isn't loaded right from the start, but gets delivered as soon as it is ready, etc...

Is it? I really can't wrap my head around this one...

$(function(){
    loadme1();
    loadme2(); /* loaded from complete different parts in the code, so not possible to start loadme2 only after loadme1 has everything finished */
});

function getData(){ 
    return $.get("/pathtogetthedata", {}, function(data){

    });
}

function loadme1(){
    getData().done(function(data){           
        var obj = $.parseJSON(data); 
        /* do something with obj */
    }
}
function loadme2(){
    getData().done(function(data){ //please just wait till the first call to the same method finished and give me that data or wait till it's in a global variable and I take it from there. Only make a call if there is no jquery "promise" waiting    
        var obj = $.parseJSON(data); 
        /* do something with obj */
    }
}

You have to keep all the "callback" and then when the data ready, to call the callback you just saved for example:

var funcs = []

function exampleOfAjaxGetData(callback) {
    funcs.push(callback)
    if (funcs.length == 1) {
        setTimeout(function() {
            alert('This is need to be called once1')
            while (funcs.length > 0)
                funcs.pop()('The data return from ajax')
        }, 2000)
    }
}


exampleOfAjaxGetData(function(x) {
    alert('I got the data:' + x)
})

exampleOfAjaxGetData(function(x) {
    alert('I got the data:' + x)
})

jsFiddle: http://jsfiddle.net/yn5ayw30/

In the example I show you a function that takes 2 seconds to complete. I called the function twice. But the "setTimeout" run only once. When setTimeout complete, it will run all the function that wait for answer.

I can think of one solution here it is :

var adata = -1; // global variable data holder

function getdata()
{
    //if ajaxx call is already done and completed then return data
    if(adata != -1 && adata != -2)return adata;

    if(adata == -1) 
    {
        //function getting called first time

        adata = -2; // now we change value of adata to -2
        // we will use this -2 to check if ajaxx call is stil running
        //do ajaxx $.get call
        $.get( "url_goes_here", function( data ) {
            adata = data;// assingh received data to adata, so -2 is changed now
        });
        //now code will move to while loop part even after first call as while loop part doesn't have condition
        //thus waiting for ajaxx call to be completed even if its first call
    }
    while(adata == -2){ 
        //just a loop to delay output until call finishes
    }
    return adata;

}

Now you can use getdata() function to achieve what you want

var getDataCalled = false;
var deferred = $.Deferred();
function getData(){ 
    if(!getDataCalled) {
        getDataCalled = true;
        return $.get("/", {} , function(data) {
              deferred.resolve(data);
        });
    } else {
         console.log("returning deferred");
         return deferred;  
    }
}

How about you save when you first call your "getData" function. When it has already been called you return your own "deferred" object back and resolve it when your first ajax request is finished. I hope this short code snippet speaks for itself and is easy to understand.

Calling getData() will now first make the ajax request and after that always return a deferred object you created yourself.

getData().done(function(data) {
  console.log(data);
});
getData().done(function(data) {
  console.log(data);
});
getData().done(function(data) {
  console.log(data);
});

You will see there will only be one ajax request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM