如果我创建一个Deferred对象,那么它会像我期望的那样报告进度.
var d1 = function() {
var d = $.Deferred();
d.notify('d1');
d.resolve('d1');
return d.promise();
};
d1().progress(function(a) {
log('Progress: ' + a);
});
但是,如果我使用then()链接两个Deferred对象,则不会调用进度回调.
d1().then(d1).progress(function(a) {
log('Progress: ' + a);
});
在我看来,then()应该传播进度通知,但事实并非如此.我想念什么吗?
我已经使用jQuery 1.8.0和1.8.1对它进行了测试.一个完整的工作示例在这里:http://jsfiddle.net/eWQuG/13/
解决方法:
我可以看到发生了什么,但是要解释它有些棘手.您可能需要阅读几次…
在测试1中,传递给test()的Promise是“原始Promise”,即. d1()返回的对象.简单.
在测试2中,传递给test()的对象是d1().then(d2).then(d3)产生的新promise.不太简单.这个新的Promise将仅继承原始Promise的某些属性-不包括其progressCallbacks(如在原始promise中用notify()放置的那样).这对于.then()返回的诺言是合理的,因为.then()旨在放置其自己的doneCallbacks,failCallbacks和progressCallbacks,而不是将延迟/承诺的内容传播到其紧邻的左侧.简而言之,.then()确实执行了其名称所隐含的含义-它指定在处理完先前的递延/承诺后要执行的操作.
通过保留对原始promise的引用(即d1()的输出),您可以更好地了解发生了什么,从而允许在测试2之前和之后都运行简单的测试1.
这是一个综合测试3:
log('-- Test 3 --');
var p = d1();//p is a promise
test(p);//equivalent to Test 1
test(p.then(d2).then(d3));//equivalent to Test 2
test(p);//equivalent to Test 1 again
在日志中,您将看到在两种情况下test(p)的行为都是相同的.但是,test(p.then(d2).then(d3))的行为有所不同,因为传递的对象不再是原始承诺,而是没有progressCallbacks的新承诺.
编辑
Ryan,在实现您想要的目标时可能需要考虑以下事项:
d1().then(d2).progress(function(a) {
log('Progress: ' + a);
});
链可以重新排列如下:
d1().progress(function(a) {
log('Progress: ' + a);
}).then(d2);
因此,进度回调将应用于原始诺言,并且由于.progress()将原始诺言沿链传播,因此.then()仍将像以前一样起作用.
两种版本均有效,但将在不同情况下适用.
如果我是对的,那么这可能是您问题的简短答案.