jQuery $ .when不等待延迟链完成ajax调用

时间:2017-10-27 09:53:09

标签: jquery jquery-deferred

这里我尝试按顺序加载几个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();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

小提琴 https://jsfiddle.net/ergec/fmrj6qgp/

1 个答案:

答案 0 :(得分: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

这只是两个单独的承诺链之间的竞争,这些承诺链没有排序或协调。无论哪个花费较少的时间执行都将首先达到目的。他们之间没有协调。

有关详细说明,请参阅Chaining vs. Branchingp.then().then() vs. p.then(); p.then()

而且,您对$.when(xxx).done()的使用是不必要的,根本不是问题的一部分。您可以使用xxx.done()获得相同的结果。

您只需使用一个保证链即可修复它:

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/