0

I have several lines in my code that need to be run in the right order. These lines include:

Ajax calls, Animations, and Playing Audio

I am aware of these questions: Call a function after previous function is complete

Wait until all jQuery Ajax requests are done?

How do I make jQuery wait for an Ajax call to finish before it returns?

I just need a way that I can add to the function definition so that the function would be completed first before any other action is done. My major problem is with this function1.done(function2) or the callback structure, because I have many of these, so I would want to control the sequence of execution of these lines just with their order in the code. Is there a way to do that?

    $.get(lang1_txt_path, function(data) {
    src_txt = data;
}, 'text').done(function() {
    $.get(lang2_txt_path, function(data) {
        trg_txt = data;
    }, 'text').done(function() {
        $.get(lang2_os_txt_path, function(data) {
            trg_txt_os = data;
        }, 'text').done(function() { //something
     })
    })
});

and these are the animations:

        $("#success_div").delay(1000).show(1000);
    $("#success_div").delay(500).hide(500);
    $("#success_div").fadeOut('slow', function() {
        //something else

    });

and this for the audio:

function play_audio(audio_path,audio_type){
audio = document.getElementById("audio_"+audio_type);audio.src =audio_path;audio.play();

}

play_audio(audio_path1,'general')


played_2nd_file=false;
$("#audio_player").bind("ended", function(){
        if (played_2nd_file==false){
            audio_path2="audio/"+lang2+'.'+trg_audio2
            play_audio(audio_path2,'general')
            console.log(audio_path2)
            played_2nd_file=true;

            }


    });

So, you can see, it is much hassle to make each of these wait till the previous ones are completed. Maybe there can be some good programming practices regarding how to organize them and include callbacks, but it is just so complicated, given that the code is changing very fast, so the only way is to make sure the functions are implemented in their same order within the code, so that this would be included in the definition of each function. Ideally I want something like:

ajax_load_file(file_path1)
ajax_load_file(file_path2)
ajax_load_file(file_path3)
play_success_animation()
play_success_audio()
play_transition_audio()
play_transition animation()

Thank you so much!

Community
  • 1
  • 1
hmghaly
  • 1,411
  • 3
  • 29
  • 47
  • 1
    Add your own promises to `ajax_load_file`, `play_success_animation`, `play_success_audio` etc, then you can simply chain them. – iCollect.it Ltd Jun 04 '15 at 11:25
  • 1) I want to avoid chaining 2) how does this work with audio and animations? – hmghaly Jun 04 '15 at 11:27
  • 1) Depends on your meaning of `chaining`. I just meant sequential execution via `done` or `then` on promises. 2) you just need to identify the end of the playback (audio or animation) - worst case use timers, but animation queues provide that via a `promise()` call on the element. – iCollect.it Ltd Jun 04 '15 at 11:29
  • sounds good, that's probably what I will be doing if I can't find something easier here :) – hmghaly Jun 04 '15 at 11:40
  • They *are* the simpler option... Added an example with each of the types below. :) – iCollect.it Ltd Jun 04 '15 at 12:14

3 Answers3

1

Most Ajax operations return a promise, so you can return those:

function ajax_load_file(file){
    return $.ajax(...);
}

Animations provide a promise on their queue, so

function play_success_animation()
{
    $("#success_div").delay(1000).show(1000);
    $("#success_div").delay(500).hide(500);
    $("#success_div").fadeOut('slow', function() {
        //something else

    });
    return $("#success_div").promise();
}

Audio provide an end event, but you need to connect/disconnect as required, so use on and off:

function play_transition_audio(path, type){
    var def = $.Deferred();
    play_audio(path,type);
    $("#audio_player").off("ended").on("ended", function(){
       def.resolve(path);
    });
    return def.promise();
}

Then chain either sequentially with then or done (then allows for success and fail callbacks, done only provide success), or in parallel with when:

e.g. Sequential:

   ajax_load_file(file_1).done(play_success_animation)
       .then(function(){
           return play_transition_audio("audio_path1", "general");
       });

You can either specify the function name, if it takes no params and returns a promise, or use an anonymous function in done/then.

e.g. Parallel:

   $.when(ajax_load_file(file_1), play_success_animation(), play_transition_audio("audio_path1", "general"));
iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
0

You can use .when

var d1 = $.Deferred();
var d2 = $.Deferred();

$.when( d1, d2 ).done(function ( v1, v2 ) {
    console.log( v1 ); // "Fish"
    console.log( v2 ); // "Pizza"
});

d1.resolve( "Fish" );
d2.resolve( "Pizza" );

https://api.jquery.com/jquery.when/

Second solution is to add promises to your function and run next function when first is finished Here You can read more about it.

Community
  • 1
  • 1
breq
  • 24,412
  • 26
  • 65
  • 106
0

$.when is like AND condition. if any one process getting fail, its not getting callback

var ajax = $.ajax({});
$.when(ajax).done(function(data) {

}).then(function(){

});

Three ways we can achieve this Demo

albert Jegani
  • 462
  • 5
  • 15