简体   繁体   中英

Call multiple scripts through ajax. Script 2 should be called only after Script 1 has finished its execution

I have 4 scripts which I want to call one after another through ajax.

I want to call script_2 only after script_1 has completed execution.

It means first I want to call script_1 in ajax, display the result of script_1 execution in its respective div and then call second script, show its result in second div and so on.

Currently what I am doing is creating a new ajax call inside the onreadystatechange() function (in a nested way).

Below is the pseudo-code:

var script1_ajax = new XMLHttpRequest();

script1_ajax.onreadystatechange=function() {            
    if (script1_ajax.readyState==4 && script1_ajax.status==200) {

        document.getElementById('result').innerHTML = script1_ajax.responseText;
        //create second ajax request and call it
        //similarly create two more nested ajax calls and call it
    }
}

I don't think this is the proper way of doing this. Please suggest how to do this in a less complicated way.

In two words: abstract and callback:

//abstract the AJAX code
function ajax(url,data,callback){
    var xhr = new XHR(...
    //the rest of the AJAX setup here
    xhr.onreadystatechange=function() {            
        if (xhr.readyState === 4 && xhr.status === 200) {
            callback(xhr.responseText); //execute callback
        }
    }
    xhr.send();
}

function script1(){
    //call ajax
    ajax('test1.php','somedata',function(returndata){
        //this callback gets executed when ajax is done
        document.getElementById('result').innerHTML = returndata;
        //execute next
        script2();
    });
}

function script2(){
    ajax('test1.php','somedata',function(returndata){
        document.getElementById('result').innerHTML = returndata;
        script3();
    });
}

function script3(){
    //and so on...
}

script1(); //execute first

On the otherhand, you can use jQuery.ajax , which pretty much looks the same way:

function script1(){
    $.get('url','data',function(data){
        $('#result').html(data);
        script2();
    });
}

function script2(){
    $.get('url','data',function(data){
        $('#result').html(data);
        script3();
    });
}

function script3(){
    //and so on
}

script1(); //execute first

Likely your best option is using a Javascript library, for example jQuery. jQuery has the jQuery.Deferred() object which can be used to easily represent a promise (a future result) thus allowing easy chaining of function calls. Note that $.get() , for example, returns a Deferred (see the documentation below in the page). This article also has a nice solution and a working jsfiddle, but it quites diverges from the Deferred approach, which is simply a matter of

function _get(url, params, success) {
  return function() {
    return $.get(url, params, success);
  }
}

$.get("http://host/1", {}, updateDiv)   // see the doc for $.get()
  .pipe(_get("http://host/2"))          // see $.Deferred() and pipe()
  .pipe(_get("http://host/3"))
  .pipe(_get("http://host/4"));

If you don't know jQuery, $.get(url, params, callback) is the way to make asynchronous HTTP GET requests

Note: I updated the code, since deferred.then() requires a callback (I gave it a promise) and replaced then() with pipe() , which gives the intended behavior on current jQuery versions (actually in 1.8 it seems then() is an alias to the current pipe() )

You could just do it this way. Say you had to load three scripts and the third has a callback.

$.get("js/ext/flowplayer-3.2.8.min.js")
.pipe($.get("js/eviflowplayer.js"))
.pipe($.get("js/evi.flowplayer.js", {}, function()
{
    W.EVI.FLOWPLAYER.init(elem.attr('id'));
});

There are more examples using $.getScript() .

Well actually is quite proper (idea), you can of course use jQuery and its async option in ajax call to force it be synced ( http://api.jquery.com/jQuery.ajax/ ), or do the same thing as in our code by using success() callback handling.

As go for code of this request, I am sure you are aware it fail on some browsers? and it looks bad as you got to invoke same set of functions twice, try to put them into functions, maybe wrap whole ajax request in some class/JSON.

third option is that you force sync mode yourself with setTimeout() / clearTimeout() implementation or setInterval() but it is not a way I would recommend.

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