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

jQuery $.when does not wait for deferred chain to complete ajax calls

这里我尝试顺序加载几个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>

Fiddle https://jsfiddle.net/ergec/fmrj6qgp/

您的方法无效,因为您从同一个承诺创建了两个分支。你有相当于:

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

这只是两个未排序或协调的独立承诺链之间的竞赛。执行时间短的那个会先结束。它们之间的协调度为零。

有关进一步说明,请参阅 and

而且,您对 $.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/