链式jQuery Promise时缺少进度通知

如果我创建一个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

DEMO

在日志中,您将看到在两种情况下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()仍将像以前一样起作用.

两种版本均有效,但将在不同情况下适用.

如果我是对的,那么这可能是您问题的简短答案.

上一篇:javascript-延迟函数解析


下一篇:[ERROR] [1568786222.758840]: Creation of publisher failed: Checksum does not match: 7250c1dc0b61c41