私は通常の(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();
});
});
};
最初の関数の最後に次を追加します
return $.Deferred().resolve();
両方の関数を次のように呼び出します
functionOne().done(functionTwo);
ヨッシーの答えに加えて、アニメーション用の別の非常にシンプルな(コールバックタイプ)ソリューションを見つけました。
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);
これはあなたが男を意味するものですか: http://jsfiddle.net/LF75a/
1つの関数が次の関数を起動する、というようになります。つまり、別の関数呼び出しを追加し、その下にfunctionONe
を追加します。
私が何かを逃したかどうかを知ってください、それが原因:)
に合うことを願って
orこれ: 前の関数が完了した後に関数を呼び出す
コード:
function hulk()
{
// do some stuff...
}
function simpsons()
{
// do some stuff...
hulk();
}
function thor()
{
// do some stuff...
simpsons();
}
ECMAScript 6
標準のJavaScript機能である promises
を使用しています。ターゲットプラットフォームがpromises
をサポートしていない場合は、 PromiseJs でポリフィルします。アニメーション呼び出しで.promise()
を使用して、jQueryがアニメーション用に作成するDeferred
オブジェクトを取得できます。これらのDeferreds
を ES6 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
が終了するとすぐに終了します。
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);
コールバック関数を介してそれを行うことができます。
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable, function() {
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
function function1(param、callback){...何かを行うcallback(); }
以下は、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);