Ich habe ein Problem mit normalen ( non-ajax ) - Funktionen, die viele Animationen enthalten in jedem von ihnen. Momentan habe ich einfach eine setTimeout
zwischen Funktionen, aber das ist nicht perfekt, da keine Browser/Computer gleich sind.
Zusätzliche Anmerkung: Beide haben getrennte Animationen/etc, die kollidieren.
Ich kann nicht einfach eins in die Rückruffunktion eines anderen setzen
// 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);
Gibt es sowieso in js/jQuery zu haben:
// Pseudo-code
-do FunctionOne()
-when finished :: run -> FunctionTwo()
Ich weiß über $.when()
& $.done()
Bescheid, aber diese sind für AJAX ...
jQuery hat eine exponierte Variable (die aus irgendeinem Grund in den jQuery-Dokumenten nicht aufgeführt ist) mit dem Namen $ .timers, die das derzeitige Animations-Array enthält.
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);
};
Grundlegende Verwendung:
// 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();
});
Sie können jQuery's $.Deferred
verwenden.
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);
sie können auch mehrere Verzögerungen zusammen packen:
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();
});
});
};
fügen Sie am Ende der ersten Funktion Folgendes hinzu
return $.Deferred().resolve();
rufe beide Funktionen so auf
functionOne().done(functionTwo);
Neben Yoshis Antwort habe ich eine weitere sehr einfache (Callback-Typ) Lösung für Animationen gefunden.
jQuery hat eine exponierte Variable (die aus irgendeinem Grund in den jQuery-Dokumenten nicht aufgeführt ist) mit dem Namen $ .timers , die das derzeitige Animations-Array enthält.
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);
};
Grundnutzung:
functionOne(); // one with animations
animationsTest(functionTwo);
Hoffe das hilft einigen Leuten raus!
ECMAScript 6 UPDATE
Hierfür wird eine neue JavaScript-Funktion namens Promises verwendet
functionOne (). then (functionTwo);
Ist das, was du meinst Mann: http://jsfiddle.net/LF75a/
Sie haben eine Funktion, um die nächste Funktion usw. auszulösen, d. H. Fügen Sie einen weiteren Funktionsaufruf hinzu, und fügen Sie anschließend unten Ihre functionONe
hinzu.
Bitte lass mich wissen, wenn ich etwas verpasst habe, hoffe, es passt zur Ursache :)
oder this: Funktion aufrufen, nachdem vorherige Funktion abgeschlossen ist
Code:
function hulk()
{
// do some stuff...
}
function simpsons()
{
// do some stuff...
hulk();
}
function thor()
{
// do some stuff...
simpsons();
}
promises
, eine JavaScript-Funktion des ECMAScript 6
-Standards. Wenn Ihre Zielplattform promises
nicht unterstützt, füllen Sie sie mit PromiseJs aus.Sie können das Deferred
-Objekt, das jQuery für die Animation erstellt, mithilfe von .promise()
für den Animationsaufruf abrufen. Wenn Sie diese Deferreds
in ES6 Promises
einbinden, erhalten Sie wesentlich saubereren Code als mit Timern.
Sie können Deferreds
auch direkt verwenden, was jedoch generell nicht empfohlen wird, da sie nicht der Promises/A + -Spezifikation folgen.
Der resultierende Code würde folgendermaßen aussehen:
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();
});
Beachten Sie, dass die Funktion in Promise.all()
das Versprechen zurückgibt. Hier passiert Magie. Wenn in einem then
-Aufruf ein Versprechen zurückgegeben wird, wartet der nächste then
-Aufruf auf die Auflösung dieses Versprechens, bevor es ausgeführt wird.
jQuery verwendet für jedes Element eine Animationswarteschlange. Animationen auf demselben Element werden also synchron ausgeführt. In diesem Fall müssten Sie keine Versprechungen verwenden!
Ich habe die jQuery-Animationswarteschlange deaktiviert, um zu zeigen, wie sie mit Versprechen funktionieren würde.
Promise.all()
nimmt ein Array von Versprechen und erstellt eine neue Promise
, die beendet wird, nachdem alle Versprechen im Array beendet wurden.
Promise.race()
nimmt auch eine Reihe von Versprechen entgegen, endet jedoch, sobald die erste Promise
beendet ist.
Sie können das Javascript Promise
und async/await
verwenden, um einen synchronisierten Aufruf der Funktionen zu implementieren.
Angenommen, Sie möchten n
die Anzahl der Funktionen synchron ausführen, die in einem Array gespeichert sind.
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);
Sie können dies über die Rückruffunktion tun.
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable, function() {
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
funktion Funktion1 (Param, Callback) { ...Sachen machen Ruf zurück();}
Hier ist eine Lösung für n-Calls (rekursive Funktion) . 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);