.done()
终止了promise链,确保没有其他可以附加更多步骤了。这意味着jQuery promise实现可以抛出任何未处理的异常,因为没有人可以使用.fail()
处理它。实际上,如果您不打算在承诺上附加更多步骤,则应使用.done()
。有关更多详细信息,请参见why promises need to be done
我一直在阅读有关jQuery的递归和诺言,但我看不出使用.then()
和.done()
进行成功的回调之间的区别。我知道Eric Hynds提到.done()
和.success()
映射到相同的功能,但是我猜想.then()
也是这样,因为所有回调都在成功完成操作时被调用。
任何人都可以启发我正确使用吗?
解决延迟问题后,将触发done()
附带的回调。当延迟被拒绝时,将触发附加到fail()
的回调。
在jQuery 1.8之前,then()
只是语法糖:
promise.then( doneCallback, failCallback )
// was equivalent to
promise.done( doneCallback ).fail( failCallback )
从1.8开始,then()
是pipe()
的别名,并返回新的Promise,有关here的更多信息,请参见pipe()
。
success()
和error()
仅在通过调用jqXHR
返回的ajax()
对象上可用。它们分别是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()
相同。
处理返回结果的方式也有所不同(称为链接,done
不链接,而then
生成调用链)
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.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()
只有一个回调,它是成功回调
.then()
同时具有成功和失败回调
[.fail()
只有一个失败回调
因此取决于您,您必须执行的操作...您是否在乎它是否成功?
仅将处理程序添加为仅在延迟解决后才被调用。您可以添加多个要调用的回调。
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);
添加要被调用的处理程序当延迟,解析,拒绝或仍在进行中时。
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);
}
实际上,就jQuery的Deferreds而言,它是Promises的实现(实际上jQuery3.0试图将它们纳入规范),实际上存在一个非常关键的区别。
完成/然后之间的主要区别是
.done()
始终返回与开始时相同的Promise /包装值,无论您执行什么操作或返回什么。 .then()
总是返回一个新的Promise,并且您负责根据传递给它的函数所返回的内容来控制Promise的内容。 [从jQuery转换为本地ES2015 Promises,.done()
有点像在Promise链中围绕函数实现“ tap”结构,因为如果链处于“ resolve”状态,它将传递一个值到一个函数...但是该函数的结果不会影响链本身。
const doneWrap = fn => x => { fn(x); return x };
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(doneWrap(console.log.bind(console)));
$.Deferred().resolve(5)
.done(x => x + 1)
.done(console.log.bind(console));
它们都将记录5,而不是6。
请注意,我使用done和doneWrap进行日志记录,而不是.then。那是因为console.log函数实际上不返回任何东西。如果您传递.then函数不返回任何内容,会发生什么?
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(console.log.bind(console))
.then(console.log.bind(console));
将记录:
5
未定义
发生了什么事?当我使用.then并将其传递给一个不返回任何内容的函数时,它的隐式结果是“未定义” ...当然,该结果将Promise [undefined]返回给下一个then方法,该方法记录了未定义。因此,我们最初使用的原始值基本上已经丢失。
.then()
本质上是函数组合的一种形式:每个步骤的结果都用作下一步中该函数的参数。这就是为什么.done最好被认为是“敲击”的原因->它实际上不是组合的一部分,而只是在某个步骤中偷偷看了一下值并在该值下运行了函数,但实际上并没有改变以任何方式组成。
这是一个非常根本的区别,并且很可能有一个很好的理由,为什么本地Promises本身没有实现.done方法。我们无需深入探讨为什么没有.fail方法,因为这更加复杂(即,.fail / .catch不是.done / .then的镜像,.catch中返回裸值的函数不会就像传递给.then的那些人一样,“ stay”被拒绝了,他们解决了!
then()
始终表示在任何情况下都将调用它。但是传递的参数在不同的jQuery版本中是不同的。
响应中有一个非常简单的心理映射,在其他答案中很难找到:
[let d = $.Deferred();
d.done(() => console.log('then'));
d.resolve();
console.log('now');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
这将输出:
then
now
现在,在相同的代码段中将
done()
替换为then()
:
var d = $.Deferred();
d.then(() => console.log('then'));
d.resolve();
console.log('now');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
现在输出:
now
then
因此,对于立即解决的延迟,传递给done()
的函数将始终以同步方式调用,而传递给then()
的任何参数都将异步调用。
.done()
终止了promise链,确保没有其他可以附加更多步骤了。这意味着jQuery promise实现可以抛出任何未处理的异常,因为没有人可以使用.fail()
处理它。实际上,如果您不打算在承诺上附加更多步骤,则应使用.done()
。有关更多详细信息,请参见why promises need to be done
.done()
终止了promise链,确保没有其他可以附加更多步骤了。这意味着jQuery promise实现可以抛出任何未处理的异常,因为没有人可以使用.fail()
处理它。实际上,如果您不打算在承诺上附加更多步骤,则应使用.done()
。有关更多详细信息,请参见why promises need to be done