0

我正在尝试使用以下进度功能创建一个基本承诺:

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 对象上调用了进度函数,但是它到达了此代码(base.js 的第 1447 行)并且未定义侦听器:

function progress(promise, value) {
        var listeners = promise._listeners;
        if (listeners) {

知道我在处理进度事件时缺少什么吗?

4

2 回答 2

3

它实际上按设计工作,但不一定按预期工作。progress为任何当前的侦听器调用。但是,由于您的方法是完全同步的,因此在第一次调用时没有连接任何侦听器。与其他 Promise 功能不同,这有点不同,因为仍然可以调用其他功能,例如完整和错误。

如果你包装你的 asyncCall 代码,你可以看到这个:

function asyncCall() {
    return new WinJS.Promise(function (complete, error, progress) {
        setImmediate(function() {
           progress('hello!');
           setTimeout(function() {
               complete();
           }, 1000);
        }, 0); 
    };

}
于 2013-09-13T21:17:28.370 回答
1

发生的事情是您调用 progress() 与创建新的 WinJS.Promise 同步发生。也就是说,WinJS.Promise 类被实例化,并且作为其初始化的一部分,它调用您的匿名初始化程序,其中包含完整、错误和进度调度程序,正如我所说的那样。

这些调度程序每个都管理一个附加到它们的处理程序数组(“侦听器”),因此当您调用它们时,就像您使用 progress() 和 complete() 一样,它们遍历该数组并调用每个处理程序反过来。

但是,在执行的这一点上,没有任何处理程序被附加到任何东西,因为 asyncCall 还没有返回,事实上,新的 WinJS.Promise 还没有返回。所以你的通话进度(“一些进展”)发生得很好,但是调度程序没有附加的处理程序,所以什么也没有发生。

你完成的处理程序被调用,因为 setTimeout 产生 UI 线程,允许你的初始化程序返回,允许 WinJS.Promise 构造函数返回,允许 asyncCall 返回一个新的承诺。只有在这一点上,您对 promise 的调用才会附加您的已完成和进度处理程序。所以一秒钟后,当超时返回时,对 complete() 的调用会调用您的处理程序。

简而言之,您的进度处理程序永远不会被调用,因为您的 Promise 初始化程序在创建 Promise 时同步调用它。尝试在初始化程序中执行以下操作:

setTimeout(function () {
   progress("some progress");
}, 100);

这也将让您退出 Promise 创建,这样您的进度处理程序将被附加。您还可以执行 setInterval 以每 100 毫秒调用一次进度,确保在 1 秒完成超时发生时取消间隔。然后你会看到对你的进度处理程序的重复调用。

底线是,在 promise 初始化程序中对完成、错误或进度的任何同步调用都不会触及传递给 then 的处理程序,因为 then 不会被调用。

于 2013-09-13T21:03:11.613 回答