jQuery 的 Deferred
有两个函数可用于实现函数的异步链接:
then()
deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred
doneCallbacks A function, or array of functions, called when the Deferred is resolved.
failCallbacks A function, or array of functions, called when the Deferred is rejected.
pipe()
deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise
doneFilter An optional function that is called when the Deferred is resolved.
failFilter An optional function that is called when the Deferred is rejected.
我知道 then()
比 pipe()
存在的时间要长一些,所以后者肯定会增加一些额外的好处,但我不知道究竟有什么区别。两者采用几乎相同的回调参数,尽管它们的名称不同,而且返回 Deferred
和返回 Promise
之间的区别似乎很小。
我一遍又一遍地阅读官方文档,但总是觉得它们太“密集”,无法真正理解,搜索发现有很多关于一个功能或另一个功能的讨论,但我没有找到任何真正阐明了各自的优缺点。
那么什么时候使用then
比较好,什么时候使用pipe
比较好?
加法
Felix's excellent answer确实有助于阐明这两个功能的不同之处。但我想知道是否有时 then()
的功能优于 pipe()
。
很明显 pipe()
比 then()
更强大,而且似乎前者可以做后者可以做的任何事情。使用 then()
的一个原因可能是它的名称反射(reflect)了它作为处理相同数据的函数链的终止的作用。
但是是否有一个用例需要 then()
返回原始的 Deferred
而 pipe() 无法完成
因为它返回了一个新的 Promise
?
最佳答案
自 jQuery 1.8 .then
的行为与 .pipe
相同:
Deprecation Notice: As of jQuery 1.8, the
deferred.pipe()
method is deprecated. Thedeferred.then()
method, which replaces it, should be used instead.
和
As of jQuery 1.8, the
deferred.then()
method returns a new promise that can filter the status and values of a deferred through a function, replacing the now-deprecateddeferred.pipe()
method.
下面的示例可能对某些人仍然有帮助。
它们有不同的用途:
.then()
将在您想要处理过程结果时使用,即如文档所述,当延迟对象被解析或拒绝时。它与使用.done()
或.fail()
相同。您将使用
.pipe()
以某种方式(预)过滤 结果。.pipe()
回调的返回值将作为参数传递给done
和fail
回调。它还可以返回另一个延迟对象,并且将在该延迟对象上注册以下回调。.then()
(或.done()
、.fail()
)不是这种情况,返回值的已注册回调将被忽略。
所以不是你使用或者 .then()
或者 .pipe()
。您可以将 .pipe()
用于与 .then()
相同的目的,但反过来不成立。
示例 1
一些操作的结果是一个对象数组:
[{value: 2}, {value: 4}, {value: 6}]
并且您想计算值的最小值和最大值。假设我们使用两个 done
回调:
deferred.then(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
var min = Math.min.apply(Math, values);
/* do something with "min" */
}).then(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
var max = Math.max.apply(Math, values);
/* do something with "max" */
});
在这两种情况下,您都必须遍历列表并从每个对象中提取值。
事先以某种方式提取值,这样您就不必在两个回调中分别执行此操作,这不是更好吗?是的!这就是我们可以将 .pipe()
用于:
deferred.pipe(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
return values; // [2, 4, 6]
}).then(function(result) {
// result = [2, 4, 6]
var min = Math.min.apply(Math, result);
/* do something with "min" */
}).then(function(result) {
// result = [2, 4, 6]
var max = Math.max.apply(Math, result);
/* do something with "max" */
});
显然这是一个虚构的例子,有许多不同的(可能更好的)方法可以解决这个问题,但我希望它能说明这一点。
例子2
考虑 Ajax 调用。有时您希望在前一个 Ajax 调用完成后启动一个 Ajax 调用。一种方法是在 done
回调中进行第二次调用:
$.ajax(...).done(function() {
// executed after first Ajax
$.ajax(...).done(function() {
// executed after second call
});
});
现在假设您想要解耦代码并将这两个 Ajax 调用放在一个函数中:
function makeCalls() {
// here we return the return value of `$.ajax().done()`, which
// is the same deferred object as returned by `$.ajax()` alone
return $.ajax(...).done(function() {
// executed after first call
$.ajax(...).done(function() {
// executed after second call
});
});
}
您想使用延迟对象来允许调用 makeCalls
的其他代码为第二个 Ajax 调用附加回调,但是
makeCalls().done(function() {
// this is executed after the first Ajax call
});
不会产生预期的效果,因为第二次调用是在 done
回调中进行的,无法从外部访问。
解决方案是使用 .pipe()
代替:
function makeCalls() {
// here we return the return value of `$.ajax().pipe()`, which is
// a new deferred/promise object and connected to the one returned
// by the callback passed to `pipe`
return $.ajax(...).pipe(function() {
// executed after first call
return $.ajax(...).done(function() {
// executed after second call
});
});
}
makeCalls().done(function() {
// this is executed after the second Ajax call
});
通过使用 .pipe()
,您现在可以将回调附加到“内部”Ajax 调用,而无需公开调用的实际流程/顺序。
一般来说,延迟对象提供了一种有趣的方式来解耦你的代码:)
关于jquery - 什么时候应该使用jQuery deferred的 "then"方法,什么时候应该使用 "pipe"方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9583783/