我可以将 Promises 传递给 jQuery.when(),还是只传递 Deferreds?

Posted

技术标签:

【中文标题】我可以将 Promises 传递给 jQuery.when(),还是只传递 Deferreds?【英文标题】:Can I pass Promises to jQuery.when(), or only Deferreds? 【发布时间】:2016-07-25 21:04:09 【问题描述】:

jQuery.when() 的documentation 表示此函数需要延迟。但是,它后来也说:

如果将单个参数传递给 jQuery.when() 并且它不是 Deferred 或 Promise...

这似乎暗示它也可以接受 Promises。但是 Promise 不是 Deferreds——它们有 Deferred 方法的一个子集。我想你可以说 Deferred 是 Promise,但 Promise 不是 Deferred。

问题:

    $.when() 可以接受 Promise 或 Deferreds 吗?这似乎在我的测试中有效。 文档中是否存在错误?我认为应该说 $.when() 接受 Promises,而不仅仅是 Deferreds。

【问题讨论】:

1.是的,它可以。 2. 可能更适合询问 jQuery 开发者。 @Karl-AndréGagnon 2. 好主意 - 我已经提交了这个 jquery 文档错误:github.com/jquery/api.jquery.com/issues/906 @JonathanAquino $.when() 可以接受jQuery.Deferred()jQuery.promise() 或本机Promise。见blog.jquery.com/2016/01/14/jquery-3-0-beta-released。 $.when() 的文档试图描述 $.when() 可以接受一个既不是jQuery.Deferred()jQuery 承诺对象也不是本机Promise 的参数,并且.then().done() 回调将处理传递参数作为解析jQuery.Deferred() @JonathanAquino jQuery 方法的一些特性可能没有详细说明,甚至没有在文档中提及。 jQuery 对象还可以使用文档中未列出的功能。一种方法是查看 jQuery github.com/jquery/jquery 的源代码以与文档中的描述进行比较。您也可以尝试在 IRC/Chat irc.jquery.org 和论坛 forum.jquery.com 提问 @guest271314:在 3.0 真正发布之前,您可以假设 jquery-tagged 问题不使用它(并且 jQuery 文档不涵盖它)。即使这样,我们也可能需要一个新标签,因为它们的行为截然不同。 【参考方案1】:

文档试图传达的是$.when() 将接受既不是jQuery.Deferred()jQuery.promise() 也不是Promise 的值;该值将被视为已解析的jQuery.Deferred(),这将在句子的下一部分进行描述

如果将单个参数传递给 jQuery.when() 并且它不是 Deferred 或 Promise,将被视为已解决的 Deferred 和 任何附加的 doneCallbacks 都会立即执行。

例如

$.when(1).then(function(data) 
  alert(data)
)
<script src="https://code.jquery.com/jquery-git.js">
</script>

【讨论】:

我在问 $.when 是否可以接受类似承诺的对象。医生说它只接受延期。但在我的测试中,它接受类似 Promise 的对象(即 Deferred.promise())。 @JonathanAquino “文档说它只接受 Deferreds。” 文档在哪里说明了这一点? $.when() 接受任何变量或对象作为参数;不仅jQuery.Deferred()。 “类似承诺的对象”是什么意思?您想使用$.when() 实现什么目标? @JonathanAquino "如果将单个参数传递给 jQuery.when() 并且它不是 Deferred 或 Promise,它将被视为已解决的 Deferred 并且附加的任何 doneCallbacks 将被立即执行。” jQuery.when() documentation 它声明它只接受 api.jquery.com/jquery.when 顶部的 Deferreds - jQuery.when( deferreds ) 我的观点是 when() 将 Deferreds 和 Promises 与其他对象区别对待。文档的顶部应该说 jQuery.when(promises),而不是 jQuery.when(deferreds),因为 promises 比 deferreds 更通用。【参考方案2】:

我想你可以说 Deferred 是 Promise,但 Promise 不是 Deferred。

实际上它们是完全不同的接口,只是将 jQuery 混入了 promise API 到它们的 deferred 中。见What are the differences between Deferred, Promise and Future in javascript?

$.when() 可以接受 Promise 或 Deferreds 吗?

是的,两者都可以。但是请注意,当您已经知道有一个 promise 或 deferred 时,调用 $.when 是没有意义的。

文档中有错误吗?

是的,显然。甚至它只是将延迟和承诺视为异步值,这甚至不是事实——而是它进行了某种鸭子类型检查。你会想看看actual implementation:

if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) )

然后它调用该值的promise method(或another promise method,或实际上任何.promise 方法)并期望返回的对象具有相应的可链接方法来添加侦听器。

【讨论】:

这部分文档似乎实际上是在描述 $.when() 接受任何参数 - 不仅是 jQuery.Deferred() jQuery .promise() 对象或原生 Promise ;并将该参数视为已解析的jQuery.Deferred()。 OP 在原始问题的引用中省略了句子的其余部分;因此可能会混淆文档引用及其试图传达的内容 - 以及当前的问题。 OP 可能试图询问 jQuery.Deferred() 和 jQuery .promise() 对象之间有什么区别 - 可能还有 Promise;虽然这在 Question 中并不清楚。 @guest271314:当然,它认为每个人都清楚,任何未被标识为“可承诺”的值都将被直接视为履行值。我的回答只是澄清了什么是“有希望的”,什么不是。 您能否扩展一下“但是请注意,当您已经知道有一个promise 或deferred 时,再调用$.when 是没有意义的。”?我对 Promise 和 Deferred 仍然很模糊,我想稍微解释一下为什么(没有意义)会对我和未来的访问者都有帮助。 @StephenP:我的意思是,你应该只做$.ajax(…).then(…),而不是做$.when($.ajax(…)).then(…)(就像文档中可怕的例子)。 $.when 仅在您有用户(函数的调用者)提供的值并且不知道它们是承诺还是普通值时才有效:$.when(couldBeAnything).then(function(nowSurelyIsPlainValue) …) @Bergi 你说“但是请注意,当你已经知道有一个 promise 或 deferred 时,调用 $.when 是没有意义的。”我认为 $.when 会将几个 Promise 组合在一起 - 这不是使用它的好理由吗?

以上是关于我可以将 Promises 传递给 jQuery.when(),还是只传递 Deferreds?的主要内容,如果未能解决你的问题,请参考以下文章

将值传递给下一个 Promises 参数

使用 Promises 执行流程,将一个函数的输出作为下一个函数的输入传递

如何将多个 PHP 变量传递给 jQuery 函数?

将变量传递给 jQuery 插件参数

将php数组传递给jquery函数

将 ASP.NET 会话传递给 jQuery