我正在学习使用jQuery 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不成功和/或返回的结果未通过我的手动验证,请警告用户并运行一些代码,例如bar()。)

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

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

我一开始无法初始化def2(ajax调用2)和def3(ajax调用3)的原因是我想根据ajax调用1的返回结果来修改ajax调用2的选项。 ajax调用3,具体取决于ajax调用2的结果。

以我有限的知识和对递延的理解,以上代码基本上无法产生我想要的东西。

因为def1在def2初始化和启动之前就已解析,所以底层代码将在def2初始化之前过早运行foo()。

因此,我正在寻求帮助和建议。看看是否有人有办法重写上面的代码并使它像我上面写的意图那样运行。很抱歉,我无能为力。

谢谢大家。

最佳答案

您不需要使用when,当您要并行运行多个延期时,确实更好。尝试这个:

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) {

})

10-07 19:42