我一直在阅读jQuery的延迟和承诺,我看不出使用.then()和.done()成功回调之间的区别。我知道Eric Hynds提到.done()和.success()映射到相同的功能,但我猜.then()也是如此,因为所有的回调都是在成功操作完成时调用的。
有人能告诉我正确的用法吗?
我一直在阅读jQuery的延迟和承诺,我看不出使用.then()和.done()成功回调之间的区别。我知道Eric Hynds提到.done()和.success()映射到相同的功能,但我猜.then()也是如此,因为所有的回调都是在成功操作完成时调用的。
有人能告诉我正确的用法吗?
当前回答
.done()终止承诺链,确保没有其他步骤可以附加。这意味着jQuery承诺实现可以抛出任何未处理的异常,因为没有人可以使用.fail()处理它。
实际上,如果您不打算为承诺附加更多步骤,则应该使用.done()。要了解更多细节,请参阅为什么需要兑现承诺
其他回答
deferred.done ()
添加仅在Deferred被解析时调用的处理程序。您可以添加多个回调被调用。
var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).done(doneCallback);
function doneCallback(result) {
console.log('Result 1 ' + result);
}
你也可以这样写在上面,
function ajaxCall() {
var url = 'http://jsonplaceholder.typicode.com/posts/1';
return $.ajax(url);
}
$.when(ajaxCall()).then(doneCallback, failCallback);
deferred.then ()
当Deferred被解析、拒绝或仍在进行时,添加要调用的处理程序。
var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).then(doneCallback, failCallback);
function doneCallback(result) {
console.log('Result ' + result);
}
function failCallback(result) {
console.log('Result ' + result);
}
在处理返回结果的方式上也有区别(它被称为链接,done不链接,然后产生调用链)
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
return 123;
}).then(function (x){
console.log(x);
}).then(function (x){
console.log(x)
})
将记录以下结果:
abc
123
undefined
而
promise.done(function (x) { // Suppose promise returns "abc"
console.log(x);
return 123;
}).done(function (x){
console.log(x);
}).done(function (x){
console.log(x)
})
将得到以下结果:
abc
abc
abc
---------- 更新:
顺便说一句。我忘了说,如果你返回一个Promise而不是原子类型值,外部Promise将等待内部Promise解决:
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
return $http.get('/some/data').then(function (result) {
console.log(result); // suppose result === "xyz"
return result;
});
}).then(function (result){
console.log(result); // result === xyz
}).then(function (und){
console.log(und) // und === undefined, because of absence of return statement in above then
})
通过这种方式,组合并行或顺序异步操作变得非常简单,例如:
// Parallel http requests
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
var promise1 = $http.get('/some/data?value=xyz').then(function (result) {
console.log(result); // suppose result === "xyz"
return result;
});
var promise2 = $http.get('/some/data?value=uvm').then(function (result) {
console.log(result); // suppose result === "uvm"
return result;
});
return promise1.then(function (result1) {
return promise2.then(function (result2) {
return { result1: result1, result2: result2; }
});
});
}).then(function (result){
console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
console.log(und) // und === undefined, because of absence of return statement in above then
})
上面的代码并行地发出两个http请求,从而使请求更快地完成,而下面这些http请求则按顺序运行,从而减少服务器负载
// Sequential http requests
promise.then(function (x) { // Suppose promise returns "abc"
console.log(x);
return $http.get('/some/data?value=xyz').then(function (result1) {
console.log(result1); // suppose result1 === "xyz"
return $http.get('/some/data?value=uvm').then(function (result2) {
console.log(result2); // suppose result2 === "uvm"
return { result1: result1, result2: result2; };
});
});
}).then(function (result){
console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
console.log(und) // und === undefined, because of absence of return statement in above then
})
.done()终止承诺链,确保没有其他步骤可以附加。这意味着jQuery承诺实现可以抛出任何未处理的异常,因为没有人可以使用.fail()处理它。
实际上,如果您不打算为承诺附加更多步骤,则应该使用.done()。要了解更多细节,请参阅为什么需要兑现承诺
除了以上的答案:
then的真正强大之处在于能够以一种流畅的方式连接ajax调用,从而避免回调地狱。
例如:
$.getJSON( 'dataservice/General', {action:'getSessionUser'} )
.then( function( user ) {
console.log( user );
return $.getJSON( 'dataservice/Address', {action:'getFirstAddress'} );
})
.then( function( address ) {
console.log( address );
})
这里第二个.then跟在返回的$.getJSON后面
附加到done()的回调将在延迟被解决时被触发。当延迟被拒绝时,附加到fail()的回调将被触发。
在jQuery 1.8之前,then()只是语法糖:
promise.then( doneCallback, failCallback )
// was equivalent to
promise.done( doneCallback ).fail( failCallback )
从1.8开始,then()是pipe()的别名,并返回一个新的promise,有关pipe()的更多信息,请参阅这里。
success()和error()仅在调用ajax()返回的jqXHR对象上可用。它们分别是done()和fail()的别名:
jqXHR.done === jqXHR.success
jqXHR.fail === jqXHR.error
同样,done()不局限于单个回调,它会过滤掉非函数(尽管在1.8版本中有一个字符串错误,应该在1.8.1中修复):
// this will add fn1 to 7 to the deferred's internal callback list
// (true, 56 and "omg" will be ignored)
promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 );
fail()也是一样。