1. ホーム
  2. javascript

[解決済み] 3つの関数を順番に実行するには、どのように呼び出せばよいですか?

2022-04-25 08:56:42

質問

この関数を次々と呼び出す必要がある場合。

$('#art1').animate({'width':'1000px'},1000);        
$('#art2').animate({'width':'1000px'},1000);        
$('#art3').animate({'width':'1000px'},1000);        

jQueryでは、こんなことができるんですね。

$('#art1').animate({'width':'1000px'},1000,'linear',function(){
    $('#art2').animate({'width':'1000px'},1000,'linear',function(){
        $('#art3').animate({'width':'1000px'},1000);        
    });        
});        

しかし、jQueryを使わず、呼び出したいと仮定しよう。

some_3secs_function(some_value);        
some_5secs_function(some_value);        
some_8secs_function(some_value);        

を実行するために、この関数をどのように呼び出せばよいのでしょうか? some_3secs_function を実行し、その呼び出しが終了した後に some_5secs_function を呼び出し、その呼び出しが終了した後に some_8secs_function ?

UPDATE

これでもダメなんです。

(function(callback){
    $('#art1').animate({'width':'1000px'},1000);
    callback();
})((function(callback2){
    $('#art2').animate({'width':'1000px'},1000);
    callback2();
})(function(){
    $('#art3').animate({'width':'1000px'},1000);
}));

3つのアニメーションを同時に開始

私の間違いはどこにあるのでしょうか?

どうすればいいですか?

Javascriptでは シンクロナス 非同期 関数を使用します。

同期関数

Javascriptのほとんどの関数は同期型です。もし、いくつかの同期関数を連続して呼び出すとしたら、以下のようになります。

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

が順番に実行されます。 doSomethingElse が開始されるまで doSomething が完了したことを示します。 doSomethingUsefulThisTime を実行するまで開始されません。 doSomethingElse が完了しました。

非同期関数

しかし、非同期関数はお互いを待つことはありません。先ほどのコードサンプルを、今度は関数が非同期であると仮定して見てみましょう。

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

関数は順番に初期化されますが、すべてほぼ同時に実行されます。どれが先に終了するかは一貫して予測できません。たまたま実行時間が最も短かったものが先に終了します。

しかし、非同期の関数を順番に実行させたい場合もあれば、同期の関数を非同期に実行させたい場合もあります。幸いなことに、これはそれぞれコールバックとタイムアウトを使えば可能だ。

コールバック

ここでは、順番に実行したい3つの非同期関数があると仮定します。 some_3secs_function , some_5secs_function および some_8secs_function .

Javascriptでは関数を引数として渡すことができるので、関数が完了した後に実行されるコールバックとして関数を渡すことができます。

このように関数を作成すると

function some_3secs_function(value, callback){
  //do stuff
  callback();
}

のように、順番に呼び出すことができます。

some_3secs_function(some_value, function() {
  some_5secs_function(other_value, function() {
    some_8secs_function(third_value, function() {
      //All three functions have completed, in order.
    });
  });
});

タイムアウト

Javascriptでは、あるタイムアウト(ミリ秒単位)の後に関数を実行するように指示することができます。これにより、事実上、同期関数を非同期に動作させることができます。

3つの同期関数がある場合、それらを非同期で実行するために setTimeout 関数を使用します。

setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);

しかし、これは少し醜いです。 DRYの原則 [ウィキペディア] . 関数の配列とタイムアウトを受け取る関数を作成することで、これを少しすっきりさせることができます。

function executeAsynchronously(functions, timeout) {
  for(var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}

これは、次のように呼び出すことができます。

executeAsynchronously(
    [doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);

まとめると、同期的に実行したい非同期関数がある場合はコールバックを、非同期的に実行したい同期関数がある場合はタイムアウトを使いましょう。