2017-10-27 10 views
0

ここで私はいくつかのJSファイルを順番に読み込もうとします。問題が$.whenの場合、チェーンが完了するまで待機しません。しかし、最後の$.Deferred.thenは期待どおりに動作します。 $.whenを動作させるにはどうすればよいですか?

var urls = [ 
 
    "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js", 
 
    "https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js", 
 
    "https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js" 
 
]; 
 
var xxx = $.Deferred(); 
 
xxx.then(function() { 
 
     options = { 
 
      dataType: "script", 
 
      url: urls[0], 
 
      cache: false 
 
     }; 
 
     return $.ajax(options).promise(); 
 
    }) 
 
    .then(function() { 
 
     options = { 
 
      dataType: "script", 
 
      url: urls[1], 
 
      cache: false 
 
     }; 
 
     return $.ajax(options).promise(); 
 
    }) 
 
    .then(function() { 
 
     options = { 
 
      dataType: "script", 
 
      url: urls[2], 
 
      cache: false 
 
     }; 
 
     return $.ajax(options).promise(); 
 
    }).then(function() { 
 
     $("body").append("This is correct. All files are loaded.<br>"); 
 
    }); 
 

 
$.when(xxx).done(function() { 
 
    $("body").append("This is wrong. JS files are not loaded yet.<br>"); 
 
}); 
 
xxx.resolve();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

フィドル https://jsfiddle.net/ergec/fmrj6qgp/

+0

あなたは '$の.when'を使用したい理由その後、予想通り、それは' $ .Deferred.then'で作業している場合は? –

+0

'$ .when()'や '$ .Deferred()'を使う理由はありません。 '$ .ajax(...)、then()'でチェーンを開始します。最後の '.then()'ハンドラは、チェーン全体がいつ完了したかを知るのにうまくいくはずです。戻り値 '$ .ajax(...)'が正常に動作するときに 'return $ .ajax()。promise()'を使う理由もありません。 – jfriend00

答えて

1

あなたが同じ約束オフ二つの枝を作成するためにあなたの方法を動作しません。

var xxx = $.Deferred(); 
xxx.then(...).then(...);  // promise chain 1 
xxx.then(...)    // promise chain 2 
xxx.resolve();    // start the race between the two promise chains 

これは、シーケンスされていない、または調整されていない2つの別々の約束チェーン間の単なる競争です。どちらを実行するのにかかる時間が短いかは、最初に終わります。それらの間には調整がありません。

さらに詳しい説明は、Chaining vs. Branchingおよびp.then().then() vs. p.then(); p.then()を参照してください。

$.when(xxx).done()の使用は不要で、実際には問題の一部ではありません。 xxx.done()と同じ結果が得られます。


は1本のだけ約束チェーンを使用してそれを修正することができます:

p.then(...).then(...).then(...) 

その後、すべてが適切に配列決定し、調整されています。

var urls = [ 
    "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js", 
    "https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js", 
    "https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js" 
]; 
let options = { 
    dataType: "script", 
    url: urls[0], 
    cache: false 
}; 
$.ajax(options).then(function() { 
    let options = { 
     dataType: "script", 
     url: urls[1], 
     cache: false 
    }; 
    return $.ajax(options); 
}).then(function() { 
    let options = { 
     dataType: "script", 
     url: urls[2], 
     cache: false 
    }; 
    return $.ajax(options).then(function() { 
      $("body").append("Last script loaded<br>"); 
    }); 
}).then(function() { 
     $("body").append("This is correct. All files are loaded.<br>"); 
}); 

の作業例:https://jsfiddle.net/jfriend00/tLp68a3q/


それとも、あなたはまだvar xxx = $.Deferred()を使用してチェーンを初期化したい場合ので、あなたはxxx.resolve()と後でそれを開始することができ、その後、あなたもそれを行うことができますが、あなたができます」 xxx.then()または$.when(xxx)を使用してください。これは、他の約束に全くリンクされていない完全に別個のブランチであるためです。

作業例$.Deferred()で始まる:https://jsfiddle.net/jfriend00/y5n3hb99/