通过更新 then() 中的 deferred 来延迟链接 jQuery?

Chaining jQuery deferred by updating deferred inside then()?

我正在学习使用 jQuery Deferred,我正在考虑链接多个 deferred。这是我的问题的简化版本:

var def1 = $.ajax(...); // ajax call 1
var def2 = null, def3 = null;

$.when(def1)
  .then(function() {
    def2 = $.ajax(...); // ajax call 2
    return def2;
  }).then(function() {
    def3 = $.ajax(...); // ajax call 3
    return def3;
  });

然后在上面代码下面的某处,我有:

$.when(def1, def2, def3)
  .then(function() {
    // run some code... .e.g. run foo();
  });

上面的代码是错误的。它不能做我想做的事。我的实际意图基本上是:

我想运行ajax先打1。

如果 ajax 呼叫 1 成功,则 运行 ajax 呼叫 2。(如果 ajax 呼叫 1 不成功,将是额外的奖励and/or 其返回结果未通过我的手动验证,提醒用户并 运行 一些代码,例如 bar()。)

如果 ajax 调用 2 成功,则 运行 ajax 调用 3。(同样的奖励适用)

然后我想 运行 一些代码(例如 foo() )只有当 def3 已经被解析时。在 运行ning foo() 之前,我实际上并不关心 def1 和 def2 是否已被解析。 (如果 def3 被拒绝,如果可能的话,我也想 运行 另一段代码。)

一开始无法初始化def2(ajax call 2)和def3(ajax call 3)的原因是我想修改[=38=的选项] 调用 2 取决于 ajax 调用 1 的返回结果。ajax 调用 3 的方式相同,取决​​于 ajax 调用 2 的结果。

以我对deferred的了解和理解有限,上面的代码基本上不能产生我想要的结果。

因为 def1 在 def2 初始化和触发之前就已解析,所以底部代码 运行 foo() 会在 def2 启动之前过早...

所以,我正在寻求帮助和建议。看看是否有人知道如何重写上面的代码并使其 运行 像我上面写的那样。对不起我的无能

提前谢谢大家。

您不需要使用 when,当您想要 运行 多个并行 deferred 时使用它确实更好。试试这个:

var d1 = $.ajax(...);
var d2 = d1.then(function () {
  if (invalid) {
    return $.Deferred().reject("Invalid");
  }
  return $.ajax(...);
});
var d3 = d2.then(function () {
  if (invalid) {
    return $.Deferred().reject("Invalid");
  }
  return $.ajax(...);
});

d3.done(function () {
  // This is called when we're all done.
});

可以简化为:

$.ajax(...).then(function () {
  if (invalid) {
    return $.Deferred().reject("Invalid");
  }
  return $.ajax(...);
}).then(function () {
  if (invalid) {
    return $.Deferred().reject("Invalid");
  }
  return $.ajax(...);
}).done(function () {
  // This is called when we're all done.
})
// Use this to handle failure. You can also add to individual
// deferred objects to handle each failure differently.
.fail(function () {
  // Do something.
});

要处理失败,您可能需要在 then:

中添加另一个回调
.then(function () {
  if (invalid) {
    return $.Deferred().reject("Invalid");
  }
  // Do stuff
}, function (err) {

})