Jquery how to run a function as soon as another function ends

* Note: repeated question:

I am trying to write the following external ones for individual function calls:

Example:

function f1 () {
    do something 1
}
function f2 () {
    do something 2   
}

run function 1
when done
run function 2

(see comments below for jsfiddles)

The problem is that the boxes are loaded at the same time. The behavior SHOULD be, load red, when done, load green.

If this isn't a normal method in jQuery, let me know, maybe I'm just chasing a ghost ...

+3


source to share


6 answers


You can just call the second function at the end of the first.

 $(document).ready(function() {

  function firstFunction(){
    alert("this is the first function!");
    secondFunction();
  }
  function secondFunction(){
    alert("this is the second function!");
  }

  firstFunction();
});

      

fiddle



Alternatively, if you don't want to call the second function every time you call the first, you can simply call them sequentially

firstFunction();
secondFunction();

      

This works because it will wait until firstFunction

it is done before it goes to the secondFunction

fiddle

+5


source


Depends on functions.

Short answer:

For synchronous functions: just call them one by one.

For asynchronous functions: depends on what makes it asynchronous.

jQuery animations? Define the callback parameter from the animation method or from the fx queue Promise.

setTimeout / setInterval / something else? The functions will most likely need to be rewritten to provide a callback or deferred / promise object.

See examples or.

Long answer:

According to jsFiddles in your comments, you have two functions:

function firstFunction(){
    $(".one").fadeIn(1000).delay(2000).fadeOut();
}
function secondFunction(){
    $(".two").fadeIn(1000).delay(2000).fadeOut();
}

      

You want to secondFunction

run after firstFunction

, and you would rather not interfere with these functions. If in this case there is only one solution I can think of: Get the Promise object from the element that is animating firstFunction

, then define it secondFunction

as a success handler:

firstFunction();
$('.one').promise().then(secondFunction);

      



jsFiddle

promise()

returns a Promise associated with the current animation state of this element. $('.one').promise().then(secondFunction)

essentially says, β€œI promise to run secondFunction

when the current animation is .one

complete.

If you want to interfere with existing functions, you can also call secondFunction

as a callback parameter fadeOut

internally firstFunction

, but this is not a very neat solution.

If you want to rewrite your functions, the ideal solution is to tame your asynchronous functions with Deferreds and Promises. Here's a quick primer:

  • In jQuery, the Deferred object is a special object that you can use to determine the success / failure status of a function. You use this in your functions.
  • The Promise object is a special object that can be used to add callbacks for these success / failure states. You use this outside of your functions.

Using these tools, you can rewrite your functions to indicate when they are "done", and you can provide code outside of your functions to know when (and after) they will be executed.

Rewritten to use pending and promises, the code looks like this:

function firstFunction(){
    var deferred = $.Deferred();
    $(".one").fadeIn(1000).delay(2000).fadeOut(function() {
        deferred.resolve();
    });
    return deferred.promise();
}
function secondFunction(){
    var deferred = $.Deferred();
    $(".two").fadeIn(1000).delay(2000).fadeOut(function() {
        deferred.resolve();
    });
    return deferred.promise();
}

firstFunction().then(secondFunction);

      

jsFiddle

If all of your functions are written this way, you can control their execution order and run them sequentially using then()

. Here's a more detailed example:

function one(){
    var deferred = $.Deferred();
    $(".one").fadeOut(500, function() {
        $(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
    });
    return deferred.promise();
}

function two(){
    var deferred = $.Deferred();
    $(".two").fadeOut(1500, function() {
        $(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
    });
    return deferred.promise();
}

function three(){
    var deferred = $.Deferred();
    $(".three").fadeOut(1000, function() {
        $(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
    });
    return deferred.promise();
}

function four(){
    var deferred = $.Deferred();
    $(".four").fadeOut(750, function() {
        $(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
    });
    return deferred.promise();
}

function five(){
    var deferred = $.Deferred();
    $(".five").fadeOut(600, function() {
        $(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
    });
    return deferred.promise();
}

one()
    .then(two)
    .then(three)
    .then(four)
    .then(five);

      

jsFiddle

+11


source


you can use jquery Callbacks function since v1.7up

var callbacks = $.Callbacks();
callbacks.add( firstFunction );
callbacks.add( secondFunction );
callbacks.fire( );

      

+4


source


Postponement is an option. You can always do the following:

$.when(firstFunction()).then(secondFunction);

      

The only trick is that inside firstFunction you will need to do the following:

function firstFunction(){
    var deferred = $.Deffered();

    $.get(url,function(r){
        deferred.resolve();
    });

    return deferred;
}

      

When the function will wait until the deferral returned by the call to firstFunction is canceled. Once the deferred is resolved (in the ajax callback), the ".then" operator is triggered by calling your second function.

The jQuery docs explain the Deferred API very well.

+4


source


instead

 firstFunction(function(){
        secondFunction();
    });

      

records

firstFunction();
secondFunction();

      

+1


source


I have had this problem lately. If you have a bunch of functions that do async things, just make them all return a Deferred that you manually resolve when the async function is done. Then you can put the functions into an array and run them sequentially:

// Sample asynchronous function that returns Deferred
var f = function(name){
    console.log('Function root start', name);
    var d = $.Deferred();
    d.done(function(result){
        console.log('Async work finish', name, result);
    });

    setTimeout(function(){
        setTimeout(function(){
            d.resolve('Hello');
        }, 200);
    }, 1000);

    console.log('Function root finish', name);
    return d;
};

// Array with functions
var defs = [];
defs.push(f.bind(null, 1));
defs.push(f.bind(null, 2));
defs.push(f.bind(null, 3));

// Recursive sequential calling
var i = 0;
var runAtIndex = function (i) {
    i < defs.length && defs[i]().done(function() { runAtIndex(i + 1); });
}
runAtIndex(i);

      

0


source







All Articles