jquery, how to run a function as soon as another function ends

前端 未结 6 1822
梦谈多话
梦谈多话 2021-01-12 18:58

*Note: Re-writing question:

I am trying to write the following outside of the individual function calls:

example:

function f1(){
         


        
相关标签:
6条回答
  • 2021-01-12 19:02

    Depends on the functions.

    Short answer:

    For synchronous functions: Just call them one after the other.

    For asynchronous functions: Depends on what makes it asynchronous.

    jQuery animations? Define a callback parameter from the animation's method or from the fx queue's Promise object.

    setTimeout/setInterval/something else? Most likely, the functions will need to be rewritten to provide a callback or Deferred/Promise object.

    See this or this for examples.

    Long answer:

    According to the jsFiddles in your comments, you've got these two functions:

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

    You want secondFunction to run after firstFunction, and you'd prefer not to tamper with these functions. If that's the case, there's only one solution I can think of: Get a Promise object from the element that firstFunction is animating, and then define secondFunction as a success handler:

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

    jsFiddle

    promise() returns a Promise object bound to the current animation state of that element. $('.one').promise().then(secondFunction) is essentially saying "I promise to run secondFunction when the current animation for .one is done.

    If you're willing to tamper with the existing functions, you could also call secondFunction as a callback parameter of the fadeOut within firstFunction, but that's not a very elegant solution.

    If you're willing to rewrite your functions, the ideal solution is to tame your async functions by using Deferreds and Promises. Here's a quick primer:

    • In jQuery, a Deferred object is a special object you can use to define the success/fail state of a function. You use this inside your functions.
    • A Promise object is a special object that you can use to add callbacks to those success/fail states. You use this outside your functions.

    Using these tools, you can rewrite your functions to specify when they're "done," and you can give code outside your functions the ability to know when (and execute after) they're done.

    Rewritten to use Deferred and Promise, 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 your functions are written this way, you can control their execution order and have them run sequentially using then(). Here's a more thorough 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

    0 讨论(0)
  • 2021-01-12 19:02

    Deferreds are an option. You could always do the following:

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

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

    function firstFunction(){
        var deferred = $.Deffered();
    
        $.get(url,function(r){
            deferred.resolve();
        });
    
        return deferred;
    }
    

    The when function will wait until the deferred returned by the firstFunction call is resolved. Once the deferred is resolved (in the ajax success callback) the '.then' statement will fire, calling your secondFunction.

    The jQuery docs explain the Deferred API very well.

    0 讨论(0)
  • 2021-01-12 19:13

    you can use the jquery Callbacks function, from v1.7up

    var callbacks = $.Callbacks();
    callbacks.add( firstFunction );
    callbacks.add( secondFunction );
    callbacks.fire( );
    
    0 讨论(0)
  • 2021-01-12 19:13

    instead of

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

    write

    firstFunction();
    secondFunction();
    
    0 讨论(0)
  • 2021-01-12 19:21

    You could simply 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 do not wish to call the second function every time you call the first, you could simply call them sequentially

    firstFunction();
    secondFunction();
    

    This works because it will wait until firstFunction is done before it moves on to secondFunction fiddle

    0 讨论(0)
  • 2021-01-12 19:24

    I had this problem recently. If you have a bunch of functions that do async stuff, just make them all to return a Deferred, which you manually resolve when the function async job is finished. Then you can put the functions in 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 讨论(0)
提交回复
热议问题