jQuery 的延迟回调执行序列

Posted

技术标签:

【中文标题】jQuery 的延迟回调执行序列【英文标题】:jQuery's Deferred callback execution sequence 【发布时间】:2013-04-25 02:14:01 【问题描述】:

jQuery 的 Deferred/promise 有两种结果:resolved 和 denied。您可以将回调附加到与任一状态关联的 Deferred。附件的条件是完成(与已解决相关)、失败(与拒绝相关)和始终(与两种状态相关)。当状态从挂起变为非挂起时,我一直试图确定回调的顺序,但没有成功;即,对于 done 和 always(或 fail 和 always),对于每个已解决和已拒绝的状态,回调执行的顺序是什么?

【问题讨论】:

我很确定它没有定义。它不应该被真正定义,你永远不需要依赖它。 非常明确。首先,将调用失败或完成。接下来,总是会被调用。它不能是任何其他顺序。回调将触发 fifo 先进先出规则:DEMO. 正如@Beetroot-Beetroot 的演示所表明的那样,它完全是先进先出,而不是 Kevin-B 建议的完成/失败总是先于。应该有人将 Beetroot-Beetroot 的评论作为答案 - 它似乎是正确和明确的。 【参考方案1】:

延迟对象按照将回调添加到延迟对象的顺序处理其回调。 done() 没有优先于 always() 的优先级,反之亦然。无论您调用resolved() 还是reject(),行为都是相同的。

请看下面jsfiddle example。

原题的cmets不正确,或者至少不完全正确。

【讨论】:

【参考方案2】:

@Malcolm 的回答确实是正确的。文档在很多地方都提到了它,包括:

deferred.done()deferred.fail()“回调按照它们添加的顺序执行。” deferred.always()“当 Deferred 被解决或拒绝时,回调按添加顺序执行” jQuery.ajax()“Promise 回调——.done().fail().always().then()——按照注册的顺序被调用。”

实现细节

查看Deferred module,它使用了实现FIFO“回调列表”的Callbacks module。

以下是用于向 Deferred 对象添加回调的调用堆栈:

always() done() / fail() Callbacks.add() list.push() – 回调函数是 pushed 到列表的末尾。

这是解析/拒绝 Deferred 对象的调用堆栈:

resolve() / reject() resolveWith() / rejectWith() Callbacks.fireWith() Callbacks.fire() – 列表中的回调使用 a for loop 按 FIFO 顺序执行。

【讨论】:

以上是关于jQuery 的延迟回调执行序列的主要内容,如果未能解决你的问题,请参考以下文章

jquery的deferred使用详解

jQuery ajax 请求作为延迟 - 包装失败回调

前端多层回调问题解决方案之$.Deferred

扭曲的延迟/回调和异步执行

Jquery 延迟对象

jQuery: Deferred