我一直遇到jQuery.Deferred.prototype.then
的问题,
所以我决定查看jQuery的测试套件来检查我是否
正确理解这种方法的行为。
与我的问题最相关的测试如下,来自
版本3.2.1:
https://github.com/jquery/jquery/blob/3.2.1/test/unit/deferred.js#L133-L168
注意:
Deferred
对象。done
。
我对QUnit并不熟悉,但它很清楚
我,测试将失败,除非
传递给done
的回调实际上已执行。done
对象时,才应执行传递给Deferred
的回调
已经解决,而不是被拒绝。
(这是我对Deferred
的理解
documentation,
反正。)但以上3点不可能都是正确的!
对done
的两次调用都是在返回的对象上进行的
jQuery.Deferred.prototype.then
。我可以解释一下
代码,如果我在Promise
返回的then
对象中假定该代码,
最终状态与原始状态不同
Deferred
。但是,我在jQuery中找不到任何暗示
文档。
尽可能简短地提出我的问题:何时
我执行上面链接的代码是回调
传递给done
执行的,如果是,为什么?
更新
以下是我上面链接的代码(添加了一些注释来表示行号):
QUnit.test( "jQuery.Deferred.then - filtering (fail)", function( assert ) {
assert.expect( 4 );
var value1, value2, value3,
defer = jQuery.Deferred(),
piped = defer.then( null, function( a, b ) {
return a * b;
} ),
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
piped.done( function( result ) { // Line 144
value3 = result;
} );
defer.fail( function( a, b ) {
value1 = a;
value2 = b;
} );
defer.reject( 2, 3 ).then( null, function() { // Line 153
assert.strictEqual( value1, 2, "first reject value ok" );
assert.strictEqual( value2, 3, "second reject value ok" );
assert.strictEqual( value3, 6, "result of filter ok" );
done.pop().call();
} );
jQuery.Deferred().resolve().then( null, function() {
assert.ok( false, "then should not be called on resolve" );
} ).then( done.pop() );
jQuery.Deferred().reject().then( null, jQuery.noop ).done( // Line 164
function( value ) {
assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
done.pop().call();
} );
} );
更新2
事实证明,then
的行为随着2016年6月jQuery 3的发布而改变。
post
在jQuery博客上,宣布新版本:
.then()创建的Deferred的解析状态现在由 它的回调 - 异常成为拒绝值和不可回报的回报 成为实现价值。以前,拒绝处理程序返回 成为拒绝价值观。
then
的{{3}}尚未更新。
答案 0 :(得分:2)
第153行拒绝延迟对象。
这是一个非常可怕的测试,一次做很多事情。有许多延迟和许多承诺,其中一些完全无关。
请注意,在第153行,defer
延迟被拒绝,其中附加了.fail
回调,附加了.then
个回调(创建了piped
)等等第153行本身附有.then
个回调。
在第144行和第164行调用done。我对QUnit并不熟悉,但我很清楚,除非传递给done的回调实际执行,否则测试将失败。
没有。你不能混淆延迟的.done
方法和QUnit完成的回调。实际上,done
数组中存储了三个QUnit回调,每个回调都由assert.async()
创建。
当且仅当Deferred对象被解析而不是被拒绝时,应该执行传递给done的回调。
是的,这正是发生的事情。请注意,第144行和第164行中的.done
次调用不是针对被拒绝的defer
延迟,而是针对piped
承诺和.then(null, jQuery.noop)
创建的另一个匿名承诺。这些承诺是不被拒绝,它们是通过作为第二个参数传递给相应.then
调用的onrejected回调的结果来实现的。