【问题标题】:Understanding Deferred.pipe()理解 Deferred.pipe()
【发布时间】:2012-04-20 20:34:10
【问题描述】:

我一直在阅读有关 jQuery 中的延迟和承诺,但我还没有使用它。

除了方法管道之外,我对一切都非常了解。我真的不明白它是什么。

能否请一些人帮助我了解它的作用以及它可以在哪里使用?

我知道有一个问题的标题与这个问题 (here) 完全相同,但并不相同。我正在寻求帮助以理解它和一些例子。另一个问题的目的是了解为什么它在特定情况下不起作用。

【问题讨论】:

标签: jquery jquery-deferred


【解决方案1】:

基本上,Deferred.pipe()$.map() 是异步等效的。它从作为输入提供的其他值投射新值,但其目的是与延续一起使用。

让我们从一个只需要$.each() 并发出返回简单对象的AJAX 请求的示例开始。对于该对象的每个属性,我们希望其id 属性是属性键的表单控件将其值设置为属性值。我们可以这样写:

$.ajax("your/url", {
    dataType: "json"
}).done(function(data) {
    $.each(data, function(key, value) {
        $("#" + key).val(value);
    });
});

现在假设我们想在更新表单控件之前对值应用一些函数。如果我们在本地这样做,我们只需要写:

$.ajax("your/url", {
    dataType: "json"
}).done(function(data) {
    $.each(data, function(key, value) {
        // doSomethingWith() projects values synchronously, as map() does.
        $("#" + key).val(doSomethingWith(value));
    });
});

但是如果doSomethingWith() 不是在客户端实现,而是通过另一个Web 服务在服务器端实现,会发生什么?在这种情况下,我们希望将控制流链接到第二个 AJAX 请求中,并且仅在第二个请求返回时更新表单控件。 Deferred.pipe() 让这一切变得简单:

$.ajax("your/url", {
    dataType: "json"
}).pipe(function(theOriginalData) {
    return $.ajax("your/web/service/doSomethingWith", {
        data: theOriginalData,
        dataType: "json"
    });
}).done(function(theFinalData) {
    $.each(theFinalData, function(key, value) {
        $("#" + key).val(value);
    });
});

【讨论】:

  • 这两个例子在功能上是一样的吗?在.pipe 调用中调用webservice 的匿名函数迭代地 对我来说是新概念。我知道从 jQuery 1.8 开始,.pipe 方法已被弃用并被.then 取代,但您能否详细说明.each.pipe 版本之间的功能差异(如果存在)? .pipe枚举的第一个GET的返回数据如何?如果这不是它的工作方式,我认为明确调用 Web 服务的 .pipe 版本作为批处理而不是迭代工作会很有帮助。
  • @Joe,这些示例在“功能上”是相同的,只有第一个同步处理值,而第二个异步处理(通过 Web 服务)。 pipe()(现在是then())仅在第一个请求返回时调用,因此原始数据已经可用。代码看起来是迭代的,但 pipe() 返回一个承诺意味着管道的其余部分将等待该承诺被履行(或被拒绝)。
  • 我的意思是,在初始版本中,特制 JSON 中的每个值都通过doSomethingWith 运行。在.pipe() 方法中,整个特制的JSON 被发送回服务器,服务器迭代项目并应用转换,然后将其发送回,最终.done 迭代这些项目。 AKA,如果它是相同的,$.ajax("your/web/service/doSomethingWith" 将被多次调用,pipe 方法中不是这种情况,对吧?又名,pipe 不会神奇地迭代原始 JSON - 它会传递整个 JSON 块?
  • @Joe,绝对的。为数据中的每个键/值对向 Web 服务执行一个请求将是非常低效的。最好让 Web 服务批量处理数据。
  • 我同意,只是想指出这一点,因为答案推断它是相同的(我真的很好奇是否发生了一些神奇的事情)。此外,对于第一次尝试掌握 Promise/Deferred 的人(可能是基本的 jQuery,尤其是因为它是 JavaScript 并且不清楚究竟会传递什么),如果假设一切都是相同,但略有不同。
【解决方案2】:

好的,我在这里的另一个答案中看到了很多参考资料,但是阅读有时不等于理解。

我发现最容易想到 Promise 以及 .done() 与 .pipe() 的应用。每个人的行为都不一样。如果我采用 promise.done(function (result) { ... }) 那么我可以在之后添加更多 .done() 或 .fail(),因为每次调用 .done() 或 .fail( ) 返回完全相同的承诺。因此,每个函数都将与原始承诺相关联,以及它是否被解决或拒绝。

现在,将其与 .pipe() 进行对比。如果我接受 promise.pipe(function (result) { ...}) 那么 .pipe() 的结果就是一个全新的承诺!如果我随后将 .done() 或 .fail() 附加到该承诺,那么这些函数将获得 .pipe() 返回的结果的修改版本,而不是原始结果。

所以 .pipe() 根据我的经验,很少需要。它真正派上用场的唯一情况是,如果您需要在其他代码看到它之前修改从承诺返回的数据(例如,在任何其他客户端代码使用之前修改客户端 AJAX 调用的某些结果)它)或者如果您需要对事物进行排序。例如,在 Promise A 解决或拒绝之后,采取另一个行动,然后只有当这完成后,我们才希望其他代码最终触发。所有其他代码都附加到来自 .pipe() 调用的承诺 B。

这是一个最近的问题,另一个用户在使用 Promise 和 .pipe()/.done()/.when() 时遇到问题,我试图提供一些代码来阐明 jsFiddle 中每个用户的使用: Do something when all deferreds are resolved

【讨论】:

  • 很好的答案,正是我试图弄清楚为什么使用 .pipe() 而不是 .done() 的原因。
【解决方案3】:

嗨,这就是你要找的东西:)

[很好读]http://www.bennadel.com/blog/2255-Using-jQuery-s-Pipe-Method-To-Change-Deferred-Resolution.htm

引用

pipe() 方法为成功和失败提供了一个过滤器 决议(AJAX 请求)。如果原始分辨率是 成功, pipe() 过滤器要么传递一个真正成功的响应 通过;或者,它会更改分辨率,返回一个新的被拒绝 承诺。那么,如果最初的请求失败了,那将是 在我们的 API 中真正出乎意料的是, pipe() 过滤器只是通过 标准化的 API 响应结构......

带有示例的堆栈链接 Understanding jQuery Deferred.pipe()(其中包含 jsfiddle)

了解延迟和承诺?请看这里 http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/

Jquery官方API页面http://api.jquery.com/deferred.pipe/(附示例)

描述:过滤和/或链接延迟的实用方法。

deferred.pipe() 方法返回一个新的 Promise 来过滤 通过函数延迟的状态和值。 doneFilter 和 failFilter 函数过滤原始 deferred 的已解决 / 被拒绝的状态和价值观。从 jQuery 1.7 开始,该方法还接受 一个 progressFilter 函数,用于过滤对原始文件的任何调用 deferred 的 notify 或 notifyWith 方法。

【讨论】:

    猜你喜欢
    • 2011-08-20
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2019-11-26
    • 2021-06-18
    相关资源
    最近更新 更多