web-dev-qa-db-de.com

Rufen Sie eine Funktion auf, nachdem die vorherige Funktion abgeschlossen ist

Ich habe den folgenden JavaScript-Code:

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

Wie kann ich sicherstellen, dass function2 erst aufgerufen wird, nachdem function1 abgeschlossen ist?

151
Rrryyyaaannn

Geben Sie einen anonymen Rückruf an und lassen Sie ihn von function1 akzeptieren:

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


function function1(param, callback) {
  ...do stuff
  callback();
} 
177
Mike Robinson

Wenn Sie jQuery 1.5 verwenden, können Sie das neue Deferreds-Muster verwenden:

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

Bearbeiten: Aktualisierter Blog-Link:

Rebecca Murphy hatte hier eine großartige Kritik: http://rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/

86
philwinkle

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.

Versprechen sind eine neue (und viel bessere) Möglichkeit, asynchrone Operationen in JavaScript auszuführen:

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable).then(function() {
            //this function is executed after function1
            function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});


function function1(param, callback) {
    return new Promise(function (fulfill, reject){
        //do stuff
        fulfill(result); //if the action succeeded
        reject(error); //if the action did not succeed
    });
} 

Dies mag für dieses einfache Beispiel wie ein erheblicher Aufwand erscheinen, aber für komplexeren Code ist es weitaus besser als die Verwendung von Rückrufen. Sie können mühelos mehrere asynchrone Aufrufe mit mehreren then-Anweisungen verketten:

function1(someVariable).then(function() {
    function2(someOtherVariable);
}).then(function() {
    function3();
});

Sie können jQuery-Deferrds auch problemlos umschließen (die von $.ajax-Aufrufen zurückgegeben werden):

Promise.resolve($.ajax(...params...)).then(function(result) {
    //whatever you want to do after the request
});

Wie @charlietfl bemerkt, implementiert das von $.ajax() zurückgegebene jqXHR-Objekt die Promise-Schnittstelle. Es ist also nicht notwendig, es in eine Promise zu packen, es kann direkt verwendet werden:

$.ajax(...params...).then(function(result) {
    //whatever you want to do after the request
});
33
Domysee

Versuche dies :

function method1(){
   // some code

}

function method2(){
   // some code
}

$.ajax({
   url:method1(),
   success:function(){
   method2();
}
})
32
TuanTruong

Oder Sie können ein benutzerdefiniertes Ereignis auslösen, wenn eine Funktion abgeschlossen ist, und es an das Dokument binden:

function a() {
    // first function code here
    $(document).trigger('function_a_complete');
}

function b() {
    // second function code here
}

$(document).bind('function_a_complete', b);

Mit dieser Methode kann die Funktion 'b' nur NACH der Funktion 'a' ausgeführt werden, da der Trigger nur dann vorhanden ist, wenn die Funktion a beendet ist.

19
de Raad

Dies hängt davon ab, was function1 gerade macht.

Wenn function1 ein einfaches synchronisiertes Javascript ausführt, z. B. das Aktualisieren eines Div-Werts oder etwas, wird function2 nach Abschluss von function1 ausgelöst.

Wenn function1 einen asynchronen Aufruf ausführt, z. B. einen Aufruf von AJAX, müssen Sie eine "callback" -Methode erstellen (die meisten ajax-APIs verfügen über einen callback-Funktionsparameter). Dann rufen Sie function2 im Callback auf. z.B:

function1()
{
  new AjaxCall(ajaxOptions, MyCallback);
}

function MyCallback(result)
{
  function2(result);
}
2
Russell

du kannst es so machen

$.when(funtion1()).then(function(){
    funtion2();
})
1
Jay Momaya

Wenn function1 eine Synchronisierungsfunktion ist, die Sie in eine asynchrone Funktion umwandeln möchten, weil dies einige Zeit in Anspruch nimmt, und Sie keine Kontrolle darüber haben, um einen Rückruf hinzuzufügen:

function function1 (someVariable) {
    var date = Date.now ();
    while (Date.now () - date < 2000);      // function1 takes some time to complete
    console.log (someVariable);
}
function function2 (someVariable) {
    console.log (someVariable);
}
function onClick () {
    window.setTimeout (() => { function1 ("This is function1"); }, 0);
    window.setTimeout (() => { function2 ("This is function2"); }, 0);
    console.log ("Click handled");  // To show that the function will return before both functions are executed
}
onClick ();

Die Ausgabe wird sein:

Click handled

... und nach 2 Sekunden:

This is function 1
This is function 2

Dies funktioniert, weil der Aufruf von window.setTimeout () der JS-Runtine-Taskschleife eine Task hinzufügt, die ein asynchroner Aufruf ausführt, und weil das grundlegende Prinzip der "Run-to-Completion" der JS-Laufzeitumgebung dafür sorgt, dass onClick () wird nie unterbrochen, bevor es endet.

Beachten Sie, dass dies so witzig wie der Code schwer zu verstehen ist ...

0
StashOfCode

Ich hatte ein Problem damit. Obwohl der obige Code verwendet wurde, funktionierte er nicht. Später wurde mir mit anderen Hilfen klar, dass meine erste Funktion asynchron und die zweite Funktion synchron war. 

Daher wurde der asynchrone Code trotz der von mir geschriebenen Codes nach der synchronen Funktion ausgeführt.

Ich habe in meinem Fall einen Workaround gefunden, indem ich die zweite Funktion am Ende meiner ersten Funktion aufrief.

0
Rahul Makhija