webentwicklung-frage-antwort-db.com.de

Warten Sie, bis eine Funktion mit Animationen abgeschlossen ist, bis Sie eine andere Funktion ausführen

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 ...


  • MEINE AKTUALISIERTE LÖSUNG

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

http://jsfiddle.net/p22dK/

109
Yoshi

fügen Sie am Ende der ersten Funktion Folgendes hinzu

return $.Deferred().resolve();

rufe beide Funktionen so auf

functionOne().done(functionTwo);
13
quemeful

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

1
quemeful

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

Diese Antwort verwendet 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.

1
Domysee

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

0
Nidhi Shah

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

0
Zaheer Babar

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