Wait till a Function with animations is finished u

2019-01-03 07:57发布

I'm having an issue with normal (non-ajax) functions that involve lots of animations within each of them. Currently I simply have a setTimeout between functions, but this isn't perfect since no browsers / computers are the same.

Additional Note: They both have separate animations/etc that collide.

I can't simply put one in the callback function of another

// multiple dom animations / etc
FunctionOne();

// What I -was- doing to wait till running the next function filled
// with animations, etc

setTimeout(function () { 
    FunctionTwo(); // other dom animations (some triggering on previous ones)
}, 1000); 

Is there anyway in js/jQuery to have:

// Pseudo-code
-do FunctionOne()
-when finished :: run -> FunctionTwo()

I know about $.when() & $.done(), but those are for AJAX...


  • MY UPDATED SOLUTION

jQuery has an exposed variable (that for some reason isn't listed anywhere in the jQuery docs) called $.timers, which holds the array of animations currently taking place.

function animationsTest (callback) {
    // Test if ANY/ALL page animations are currently active

    var testAnimationInterval = setInterval(function () {
        if (! $.timers.length) { // any page animations finished
            clearInterval(testAnimationInterval);
            callback();
        }
    }, 25);
};

Basic useage:

// run some function with animations etc    
functionWithAnimations();

animationsTest(function () { // <-- this will run once all the above animations are finished

    // your callback (things to do after all animations are done)
    runNextAnimations();

});

9条回答
倾城 Initia
2楼-- · 2019-01-03 08:40

add the following to the end of the first function

return $.Deferred().resolve();

call both functions like so

functionOne().done(functionTwo);
查看更多
爷、活的狠高调
3楼-- · 2019-01-03 08:49

You can use jQuery's $.Deferred

var FunctionOne = function () {
  // create a deferred object
  var r = $.Deferred();

  // do whatever you want (e.g. ajax/animations other asyc tasks)

  setTimeout(function () {
    // and call `resolve` on the deferred object, once you're done
    r.resolve();
  }, 2500);

  // return the deferred object
  return r;
};

// define FunctionTwo as needed
var FunctionTwo = function () {
  console.log('FunctionTwo');
};

// call FunctionOne and use the `done` method
// with `FunctionTwo` as it's parameter
FunctionOne().done(FunctionTwo);

you could also pack multiple deferreds together:

var FunctionOne = function () {
  var
    a = $.Deferred(),
    b = $.Deferred();

  // some fake asyc task
  setTimeout(function () {
    console.log('a done');
    a.resolve();
  }, Math.random() * 4000);

  // some other fake asyc task
  setTimeout(function () {
    console.log('b done');
    b.resolve();
  }, Math.random() * 4000);

  return $.Deferred(function (def) {
    $.when(a, b).done(function () {
      def.resolve();
    });
  });
};

http://jsfiddle.net/p22dK/

查看更多
姐就是有狂的资本
4楼-- · 2019-01-03 08:51

You can use the javascript Promise and async/await to implement a synchronized call of the functions.

Suppose you want to execute n number of functions in a synchronized manner that are stored in an array, here is my solution for that.

async function executeActionQueue(funArray) {
  var length = funArray.length;
  for(var i = 0; i < length; i++) {
    await executeFun(funArray[i]);
  }
};

function executeFun(fun) {
  return new Promise((resolve, reject) => {
    
    // Execute required function here
    
    fun()
      .then((data) => {
        // do required with data 
        resolve(true);
      })
      .catch((error) => {
      // handle error
        resolve(true);
      });
  })
};

executeActionQueue(funArray);

查看更多
走好不送
5楼-- · 2019-01-03 08:54

ECMAScript 6 UPDATE

This uses a new feature of JavaScript called Promises

functionOne().then(functionTwo);

查看更多
Root(大扎)
6楼-- · 2019-01-03 08:54

You can do it via callback function.

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable, function() {
          function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});

function function1(param, callback) { ...do stuff callback(); }

查看更多
7楼-- · 2019-01-03 08:55

Is this what you mean man: http://jsfiddle.net/LF75a/

You will have one function fire the next function and so on, i.e. add another function call and then add your functionONe at the bottom of it.

Please lemme know if I missed anything, hope it fits the cause :)

or this: Call a function after previous function is complete

Code:

function hulk()
{
  // do some stuff...
}
function simpsons()
{
  // do some stuff...
  hulk();
}
function thor()
{
  // do some stuff...
  simpsons();
}
查看更多
登录 后发表回答