Javascript 等到一个带有动画的函数完成,直到运行另一个函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12116505/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:08:56  来源:igfitidea点击:

Wait till a Function with animations is finished until running another Function

javascriptjquerycallback

提问by Mark Pieszak - Trilon.io

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

我遇到了正常(非 ajax)函数的问题,这些函数在每个函数中都涉及大量动画。目前我只有一个setTimeout功能之间的功能,但这并不完美,因为没有浏览器/计算机是相同的。

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:

无论如何在 js/jQuery 中有:

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

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

我知道$.when()& $.done(),但那些是针对 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.

jQuery 有一个名为 $.timers 的公开变量(由于某种原因未在 jQuery 文档中的任何地方列出),它保存当前发生的动画数组。

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();

});

回答by Yoshi

You can use jQuery's $.Deferred

你可以使用 jQuery 的 $.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/

http://jsfiddle.net/p22dK/

回答by quemeful

add the following to the end of the first function

将以下内容添加到第一个函数的末尾

return $.Deferred().resolve();

call both functions like so

像这样调用这两个函数

functionOne().done(functionTwo);

回答by Mark Pieszak - Trilon.io

Along with Yoshi's answer, I have found another very simple (callback type) solution for animations.

随着 Yoshi 的回答,我发现了另一个非常简单的(回调类型)动画解决方案。

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.

jQuery 有一个名为$.timers的公开变量(由于某种原因未在 jQuery 文档中的任何地方列出),它保存当前发生的动画数组。

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:

基本用途:

functionOne(); // one with animations

animationsTest(functionTwo);

Hope this helps some people out!

希望这可以帮助一些人!

回答by Tats_innit

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

这是你的意思吗: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 functionONeat the bottom of it.

您将有一个函数触发下一个函数,依此类推,即添加另一个函数调用,然后functionONe在其底部添加您的。

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

请让我知道我是否遗漏了什么,希望它符合原因 :)

orthis: 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();
}

回答by Domysee

This answer uses promises, a JavaScript feature of the ECMAScript 6standard. If your target platform does not support promises, polyfill it with PromiseJs.

这个答案使用标准promises的 JavaScript 特性ECMAScript 6。如果您的目标平台不支持promises,请使用PromiseJs对其进行polyfill

You can get the Deferredobject jQuery creates for the animation using .promise()on the animation call. Wrapping these Deferredsinto ES6 Promisesresults in much cleaner code than using timers.

您可以Deferred通过.promise()动画调用获取jQuery 为动画创建的对象。将这些包装DeferredsES6 中会Promises产生比使用计时器更简洁的代码。

You can also use Deferredsdirectly, but this is generally discouraged because they do not follow the Promises/A+ specification.

您也可以Deferreds直接使用,但通常不鼓励这样做,因为它们不遵循 Promises/A+ 规范。

The resulting code would look like this:

生成的代码如下所示:

var p1 = Promise.resolve($('#Content').animate({ opacity: 0.5 }, { duration: 500, queue: false }).promise());
var p2 = Promise.resolve($('#Content').animate({ marginLeft: "-100px" }, { duration: 2000, queue: false }).promise());
Promise.all([p1, p2]).then(function () {
    return $('#Content').animate({ width: 0 }, { duration: 500, queue: false }).promise();
});

Note that the function in Promise.all()returns the promise. This is where magic happens. If in a thencall a promise is returned, the next thencall will wait for that promise to be resolved before executing.

请注意,函数 inPromise.all()返回承诺。这就是魔法发生的地方。如果在一次then调用中返回了一个承诺,下一个then调用将在执行之前等待该承诺得到解决。

jQuery uses an animation queue for each element. So animations on the same element are executed synchronously. In this case you wouldn't have to use promises at all!

jQuery 为每个元素使用一个动画队列。所以同一个元素上的动画是同步执行的。在这种情况下,您根本不必使用承诺!

I have disabled the jQuery animation queue to demonstrate how it would work with promises.

我已经禁用了 jQuery 动画队列来演示它如何与承诺一起工作。

Promise.all()takes an array of promises and creates a new Promisethat finishes after all promises in the array finished.

Promise.all()接受一组承诺并创建一个新的Promise,在阵列中的所有承诺完成后完成。

Promise.race()also takes an array of promises, but finishes as soon as the first Promisefinished.

Promise.race()也接受一系列承诺,但在第一个Promise完成后立即完成。

回答by quemeful

ECMAScript 6 UPDATE

ECMAScript 6 更新

This uses a new feature of JavaScript called Promises

这使用了 JavaScript 的一个新特性,称为 Promises

functionOne().then(functionTwo);

functionOne().then(functionTwo);

回答by Nidhi Shah

You can use the javascript Promiseand async/awaitto implement a synchronized call of the functions.

您可以使用 javascriptPromiseasync/await实现函数的同步调用。

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

假设您想以n同步方式执行存储在数组中的多个函数,这是我的解决方案。

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);

回答by Zaheer Babar

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(); }

function function1(param, callback) { ...做东西 callback(); }

回答by mathew11

Here is a solution for n-calls (recursive function). https://jsfiddle.net/mathew11/5f3mu0f4/7/

这是 n 次调用(递归函数)的解决方案。 https://jsfiddle.net/mathew11/5f3mu0f4/7/

function myFunction(array){
var r = $.Deferred();

if(array.length == 0){
    r.resolve();
    return r;
}

var element = array.shift();
// async task 
timer = setTimeout(function(){
    $("a").text($("a").text()+ " " + element);
    var resolving = function(){
        r.resolve();
    }

    myFunction(array).done(resolving);

 }, 500);

return r;
}

//Starting the function
var myArray = ["Hi", "that's", "just", "a", "test"];
var alerting = function (){window.alert("finished!")};
myFunction(myArray).done(alerting);