我一直在阅读jQuery的延迟和承诺,我看不出使用.then()和.done()成功回调之间的区别。我知道Eric Hynds提到.done()和.success()映射到相同的功能,但我猜.then()也是如此,因为所有的回调都是在成功操作完成时调用的。

有人能告诉我正确的用法吗?


当前回答

jQuery 3.0还有一个重要的区别,它很容易导致意想不到的行为,在之前的回答中没有提到:

考虑下面的代码:

let d = $.Deferred(); D.done (() => console.log('then')); d.resolve (); console.log(现在的); < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js " > < /脚本>

这将输出:

then
now

现在,将done()替换为then()在相同的代码片段中:

var d = $.Deferred(); D.then (() => console.log('then')); d.resolve (); console.log(现在的); < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js " > < /脚本>

现在的输出是:

now
then

因此,对于立即解决的延迟,传递给done()的函数将始终以同步方式调用,而传递给then()的任何参数将以异步方式调用。

这与之前的jQuery版本不同,在升级指南中提到,两个回调都是同步调用的:

遵守承诺/A+所需要的另一个行为改变是 Deferred .then()回调总是异步调用的。 以前,如果.then()回调被添加到Deferred that was 已经解决或拒绝,回调将立即运行 同步。

其他回答

除了以上的答案:

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()只有一个回调,它是成功回调

.then()有success和fail两个回调函数

.fail()只有一个失败回调

所以你该怎么做就怎么做了…你在乎成功还是失败吗?

在回答中有一个非常简单的心理映射,在其他答案中很难找到:

done实现了蓝鸟承诺中的tap 然后实现然后在ES6承诺

附加到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()也是一样。

jQuery 3.0还有一个重要的区别,它很容易导致意想不到的行为,在之前的回答中没有提到:

考虑下面的代码:

let d = $.Deferred(); D.done (() => console.log('then')); d.resolve (); console.log(现在的); < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js " > < /脚本>

这将输出:

then
now

现在,将done()替换为then()在相同的代码片段中:

var d = $.Deferred(); D.then (() => console.log('then')); d.resolve (); console.log(现在的); < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js " > < /脚本>

现在的输出是:

now
then

因此,对于立即解决的延迟,传递给done()的函数将始终以同步方式调用,而传递给then()的任何参数将以异步方式调用。

这与之前的jQuery版本不同,在升级指南中提到,两个回调都是同步调用的:

遵守承诺/A+所需要的另一个行为改变是 Deferred .then()回调总是异步调用的。 以前,如果.then()回调被添加到Deferred that was 已经解决或拒绝,回调将立即运行 同步。