web-dev-qa-db-ja.com

別の関数を実行するまで、アニメーションを含む関数が終了するまで待ちます

私は通常の(non-ajax)関数に問題があります。これらの関数には、それぞれにanimationsがたくさん含まれています。現在、私は単に関数間にsetTimeoutを持っていますが、ブラウザー/コンピューターが同じではないため、これは完全ではありません。

追加の注意:両方とも衝突する別個のアニメーション/などを持っています。

別のコールバック関数に単純に入れることはできません

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

とにかくjs/jQueryには次のものがありますか?

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

$.when()$.done()について知っていますが、それらはAJAX用です...


  • 私の更新されたソリューション

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

基本的な使用法:

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

});

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

複数の遅延オブジェクトを一緒にパックすることもできます。

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/

109
Yoshi

最初の関数の最後に次を追加します

return $.Deferred().resolve();

両方の関数を次のように呼び出します

functionOne().done(functionTwo);
13
quemeful

ヨッシーの答えに加えて、アニメーション用の別の非常にシンプルな(コールバックタイプ)ソリューションを見つけました。

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

基本的な使用法:

functionOne(); // one with animations

animationsTest(functionTwo);

これが一部の人々の助けになることを願っています!

ECMAScript 6 UPDATE

これは、Promiseと呼ばれるJavaScriptの新機能を使用します

functionOne()。then(functionTwo);

1
quemeful

これはあなたが男を意味するものですか: http://jsfiddle.net/LF75a/

1つの関数が次の関数を起動する、というようになります。つまり、別の関数呼び出しを追加し、その下にfunctionONeを追加します。

私が何かを逃したかどうかを知ってください、それが原因:)に合うことを願って

orこれ: 前の関数が完了した後に関数を呼び出す

コード:

function hulk()
{
  // do some stuff...
}
function simpsons()
{
  // do some stuff...
  hulk();
}
function thor()
{
  // do some stuff...
  simpsons();
}
1
Tats_innit

この回答では、ECMAScript 6標準のJavaScript機能である promises を使用しています。ターゲットプラットフォームがpromisesをサポートしていない場合は、 PromiseJs でポリフィルします。

アニメーション呼び出しで.promise()を使用して、jQueryがアニメーション用に作成するDeferredオブジェクトを取得できます。これらのDeferredsES6 Promises にラップすると、タイマーを使用するよりもコードがずっときれいになります。

Deferredsを直接使用することもできますが、Promises/A +仕様に準拠していないため、通常は推奨されません。

結果のコードは次のようになります。

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

Promise.all()の関数はpromiseを返すことに注意してください。これは魔法が起こる場所です。 then呼び出しでpromiseが返された場合、次のthen呼び出しは、実行する前にそのpromiseが解決されるのを待ちます。

jQueryは各要素にアニメーションキューを使用します。したがって、同じ要素のアニメーションは同期的に実行されます。この場合、Promiseを使用する必要はまったくありません!

私はjQueryアニメーションキューを無効にして、Promiseでどのように機能するかを示しました。

Promise.all()はpromiseの配列を取り、配列内のすべてのpromiseが終了した後に終了する新しいPromiseを作成します。

Promise.race()もpromiseの配列を受け取りますが、最初のPromiseが終了するとすぐに終了します。

1
Domysee

JavaScriptのPromiseおよびasync/awaitを使用して、関数の同期呼び出しを実装できます。

配列に保存されている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);
0
Nidhi Shah

コールバック関数を介してそれを行うことができます。

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

function function1(param、callback){...何かを行うcallback(); }

0
Zaheer Babar

以下は、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);
0
mathew11