我正在尝试使用进度函数创建基本承诺,例如:
asyncCall().then(function () {
that.output("complete");
},
null,
function(v) {
that.output(v);
}).done();
function asyncCall() {
return new WinJS.Promise(function (complete, error, progress) {
progress("some progress");
setTimeout(function () {
complete();
}, 1000);
});
}
我希望这会输出'进度'1秒然后显示'完成';但是,“进步”永远不会输出。调试javascript,在promise对象上调用progress函数,但它到达此代码(base.js的第1447行)并且侦听器未定义:
function progress(promise, value) {
var listeners = promise._listeners;
if (listeners) {
知道我缺少什么来处理进度事件吗?
答案 0 :(得分:3)
它实际上按设计工作,但未必如预期。任何当前侦听器都会调用progress
。但是,由于您的方法完全同步,因此在第一次调用时没有连接侦听器。与其他Promise功能不同,这有点不同,因为仍然可以调用诸如complete和error之类的其他函数。
如果你包装了asyncCall代码,你可以看到这个:
function asyncCall() {
return new WinJS.Promise(function (complete, error, progress) {
setImmediate(function() {
progress('hello!');
setTimeout(function() {
complete();
}, 1000);
}, 0);
};
}
答案 1 :(得分:1)
正在发生的事情是,您正在调用progress()与创建新的WinJS.Promise同步进行。也就是说,WinJS.Promise类被实例化,并且作为其初始化的一部分,它调用你的匿名初始化程序,包括完整的,错误的和进度调度程序,就像我调用它们一样。
这些调度程序分别管理附加到它们的处理程序数组(“侦听器”),这样当你调用它们时,就像你正在使用progress()和complete()一样,它们遍历该数组并且依次调用每个处理程序。
但是,在执行的这一点上,没有处理程序附加到任何东西,因为asyncCall尚未返回,事实上,新的WinJS.Promise尚未返回。所以你的通话进度(“一些进展”)发生得很好,但调度员没有附加处理程序,所以没有任何反应。
调试完成的处理程序因为setTimeout产生UI线程,允许初始化程序返回,允许WinJS.Promise构造函数返回,允许asyncCall返回新的promise。只有在那时,您对promise的调用才会附加已完成的进度处理程序。所以一秒钟之后,当超时回来时,对complete()的调用会调用你的处理程序。
简而言之,永远不会调用您的进度处理程序,因为您的promise初始化程序正在创建promise时同步调用它。尝试在初始化程序中执行类似的操作:
setTimeout(function () {
progress("some progress");
}, 100);
这也会让您退出创建承诺,以便附加您的进度处理程序。您还可以执行setInterval来每100ms调用一次进度,确保在1s完成超时发生时取消间隔。然后你会看到对你的进度处理程序的重复调用。
底线是对promise初始化程序内的完成,错误或进度的任何同步调用都不会触及传递给当时的处理程序,因为这样就不会被调用。