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


179

次のJavaScriptコードがあります。

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

が完了したfunction2function1にのみ呼び出されるようにするにはどうすればよいですか?


24
されたfunction1非同期操作を実行しますか?
LiraNuna、2011

8
Yads、function1にアニメーションが含まれている場合、function2はfunction1のアニメーションがまだ実行されている間に実行されます。function1で開始されたすべてが完全に完了するまで、function2をどのように待機させますか?
trusktr

誰かがfunction1が完了するまでfunction2が呼び出されないようにするために何かする必要がある理由を私に説明できますか?ここでは非同期操作は発生していないため、この操作は同期的であるため、function1が完了するまでfunction2は実行されません。
アーロン

回答:


206

匿名のコールバックを指定し、function1がそれを受け入れるようにします。

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


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

11
+1ですが、1.5を使用している場合は、新しいDeferredsパターンを使用できます
philwinkle

迅速な対応ありがとうございます。はい、function1は単純な非同期タスクを実行しているだけなので、コールバックを作成する必要があるという点で正しいと思います。または、フィルウィンクルが述べたこの遅延ビジネスを見てみましょう。みんなありがとう。私は少し眠りにつくつもりで、朝はまたこれに取り組みます。
Rrryyyaaannn

13
この答えは解決策ではありません。:ここでは動作しない証拠だjsfiddle.net/trusktr/M2h6e
trusktr

12
@MikeRobinson問題は次のとおり...do stuffです。非同期のものが含まれている場合はどうなりますか?Function2は期待どおりにまだ起動しません。上記の私のコメントの例は、foo()関数に非同期コードが含まれているため、のコンテンツの実行が完了したbar()foo()、コンテンツを順番$.when().then()に呼び出す場合でも、そのコンテンツを起動しないことを示しています。この答えは...do stuff、コード内のすべてのものが厳密に同期している場合にのみ有効です。
trusktr 2013

1
あなたはまで最初のコールバックを渡しておく必要があり、その場合には@trusktr nはその後、非同期呼び出しの番目のレベル、火災のcallBack()すべての後にn個の非同期呼び出しが行われます。OPは関数で何をしているのか言及していないので、OPはそれを1レベルの非同期呼び出しと見なしました。
GoodSp33d 2013

96

jQuery 1.5を使用している場合は、新しいDeferredsパターンを使用できます。

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

編集:更新されたブログリンク:

Rebecca Murphyはこれについて素晴らしい記事を書いています:http : //rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/


2
しかし、それは実用的な例ですか?何が延期されていますか?function1とfunction2をすぐに実行しています。(私は元のコメント者ではありません。)
user113716

10
それは私にはまったく効果がありません。function1とfunction2は両方とも正確に同時に実行されます(人間の目で観察可能)。これが小さな例です:jsfiddle.net/trusktr/M2h6e
trusktr

1
Rebecca Murphyの記事は、DifferdsがjQueryに導入される前の記事であり、それが実装されるとライターが考える方法に基づいた例を使用しています。この機能を実際に使用する方法については、jQueryのサイトにアクセスしてください。api.jquery.com
Spencer Williams

1
jQuery 1.5や現代的なものでも、$.when(function1).then(function2);(関数を呼び出す括弧なしで)欲しくないですか?
Teepeemm 2014

1
数年遅れてこれらのコメントを読んでください。 function1約束を返す必要があります。その場合、それは参照ではなく、実際に実行される関数である必要があります。ときはresolve、その約束で呼び出されfunction2実行されます。これはfunction1ajax呼び出しがあると仮定することで簡単に説明できます。doneコールバックは、約束を解決します。私はそれが明確であることを望みます。
philwinkle 2014

46

これを試して :

function method1(){
   // some code

}

function method2(){
   // some code
}

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

37

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

プロミスは、JavaScriptで非同期操作を処理するための新しい(そしてはるかに優れた)方法です。

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

これは、この単純な例では大きなオーバーヘッドのように見えるかもしれませんが、より複雑なコードの場合は、コールバックを使用するよりもはるかに優れています。複数のthenステートメントを使用して、複数の非同期呼び出しを簡単にチェーンできます。

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

jQuery遅延を簡単にラップすることもできます($.ajax呼び出しから返されます)。

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

@charlietflが述べたように、jqXHRによって返されるオブジェクト$.ajax()Promiseインターフェースを実装します。したがって、実際にでラップする必要はなくPromise、直接使用できます。

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

Promise.resolve折り返し$.ajaxはアンチパターンであり、$.ajax返却可能な約束を返します
charlietfl 2018年

@charlietflですが、実際のものではなくPromise、インターフェースを実装するだけです。実数Promiseをそれに渡すときにどのように動作するかわかりませんthenメソッドや、Promise.alla jqXHRとa Promiseが渡された場合のaの。そのために、さらにテストを行う必要があります。ヒントをありがとう、答えに追加します!
Domysee、2018年

実際、jQueryバージョン3+では、Promises A +に準拠しています。関わらずは$.ajax.then新しいものではない
charlietfl

21

または、1つの関数が完了したときにカスタムイベントをトリガーし、それをドキュメントにバインドすることもできます。

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

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

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

このメソッドを使用すると、トリガーは関数aの実行が終了したときにのみ存在するため、関数 'b'はAFTER関数 'a'しか実行できません。


「jQuery 1.7以降、.on()メソッドは、イベントハンドラーをドキュメントに添付するための推奨メソッドです。」api.jquery.com/bind
CodeVirtuoso


3

これはfunction1が何をしているかに依存します。

function1がdiv値の更新などの単純な同期JavaScriptを実行している場合、function2はfunction1が完了した後に起動します。

function1がAJAX呼び出しなどの非同期呼び出しを行っている場合は、「コールバック」メソッドを作成する必要があります(ほとんどのajax APIにはコールバック関数パラメーターがあります)。次に、コールバックでfunction2を呼び出します。例えば:

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

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

2

メソッド1をメソッド2、3、4の後に実行する必要がある場合、次のコードスニペットは、JavaScriptでDeferredオブジェクトを使用してこれを解決することができます。

function method1(){
  var dfd = new $.Deferred();
     setTimeout(function(){
     console.log("Inside Method - 1"); 
     method2(dfd);	 
    }, 5000);
  return dfd.promise();
}

function method2(dfd){
  setTimeout(function(){
   console.log("Inside Method - 2"); 
   method3(dfd);	
  }, 3000);
}

function method3(dfd){
  setTimeout(function(){
   console.log("Inside Method - 3"); 	
   dfd.resolve();
  }, 3000);
}

function method4(){   
   console.log("Inside Method - 4"); 	
}

var call = method1();

$.when(call).then(function(cb){
  method4();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


0

function1がいくつかの同期関数であり、完了するまでに時間がかかるため非同期関数にしたい場合、コールバックを追加するための制御ができません。

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

出力は次のようになります。

Click handled

...そして2秒後:

This is function 1
This is function 2

これが機能するのは、window.setTimeout()を呼び出すと、非同期呼び出しによってJS runtineタスクループにタスクが追加され、JSランタイムの「実行して完了する」という基本原則により、onClick()が確実になるためです。終了する前に中断されることはありません。

これがコードを理解するのが難しいかもしれないのと同じくらい面白いことに注意してください...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.