jQuery延迟对象中的多个done()函数——它是如何工作的?

3

最近,我询问了如何触发不同数量的jQuery get() 请求,然后我收到了这段代码作为一个非常高效且可行的解决方案:

var d = new $.Deferred();
var promise = d.promise();
var results = [];
for (var i = 0; i < 5; i++) {
    (function(i) {
        promise = promise.then(function() {
            return $.ajax('/echo/json/', {
                data: {
                    json: JSON.stringify({foo: i})
                }
            }).done(function(data) {
                results[i] = data;
            });
        });
    }(i));
}

promise.done(function() {
    console.log(results);
});

d.resolve(); 

我正在寻找关于这个多个done()附加到每个promise.then(),然后再附加到承诺本身的最终done()如何工作的解释。是否一个承诺(据我所知是一种特殊类型的延迟)可以有一个done,而延迟本身也可以有一个done?如果它不在循环中,那么连续进行三个ajax请求的语法会是什么样子?只是试图理解一下。谢谢!

fiddle

2个回答

7
如果您有一个延迟对象数组,您可以使用whenapply来处理它们,以获取承诺,然后在它们上面使用$.done()
$.when.apply($, deferredArray).done(function() {
   for (var i = 0; i < arguments.length; i++) {
      //arguments[i] is the return of the singular done() statement    
   }
});

如果你不知道有多少个延迟对象需要处理,这种方法效果相当不错。


我在第一篇帖子中收到了类似的答案,但我真的不知道apply是怎么回事。它是如何被使用的?作为第一个参数的$是什么意思?谢谢。 - 1252748
实际上,在答案中,他们将null用作第一个参数:$.when.apply(null, dfdArr).done(function () { for (response in arguments) { html_str += arguments[response][0]; - 1252748
arguments 是从哪里来的?是什么生成了它? - 1252748
  1. apply()函数允许我们将deferredArray中的每个元素传递给排序的when函数。
  2. arguments是基本的JavaScript组成部分。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments
- danielrsmith
整个代码读起来有点像英语:“当延迟数组中的所有承诺都完成时,执行此操作...” - danielrsmith

3
一个Promise是一个包装器,用于隐藏deferred的resolve和reject方法,类似于deferred的公共接口。对于then()和done(),无论您是在deferred上使用还是在其promise上使用,都没有区别。从现在开始我将同时使用这两个术语。
话虽如此,done()返回deferred本身,允许链式调用。您可以像这样添加尽可能多的done(和fail)处理程序。它们将一个接一个地被调用。
then()返回一个新的deferred*,它可以有自己的done和fail处理程序。
请注意,在您的代码中,您在每个循环迭代中都会替换变量promise中的deferred,因此最终的done()不是在原始的deferred上调用的,而是在最新的deferred上调用的,该deferred是由最后一个then()返回的。
所有在一行中链接的调用看起来像这样(每个then()都返回一个新的promise。我标记了在哪个done()方法上调用):
d.then().done().then().done().then().done().then().done().done();
         ^^^^^^        ^^^^^^        ^^^^^^        ^^^^^^^^^^^^^
        promise 1     promise 2     promise 3       promise 4

*) 实际上这是一个承诺

谢谢你的解释。我对这个有点困惑:“请注意,在你的代码中,你在每次循环迭代中都替换了 promise 变量中的延迟” promise = promise.then 看起来更像是一个连接而不是替换。这样理解对吗? - 1252748
不正确。我相信你编写了很多PHP代码?在JavaScript中,点号不是连接运算符,它就像PHP中的->;-) - Fabian Schmengler
哈哈,好的。你能解释一下最后一行的意思吗?它说“*)实际上是Promise”。 - 1252748
脚注解释:then() 返回一个新的延迟对象的承诺(它的,而不是它是),而不是延迟本身。但正如我所说,这在这里没有任何区别。 - Fabian Schmengler
1
“Promise” 是对 “deferred” 对象的包装器。就个人而言,如果将 Promise 描述为“包装器”,我可能会感到困惑,因为这不符合我的心理模型。对我来说,更好的陈述应该是,“Promise 派生自 Deferred,并公开除了解析和拒绝之外 Deferred 的所有方法。”但是如果 “wrapper” 适用于您 (和其他任何人),那么我不能说它是错误的。 - Beetroot-Beetroot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接