Javascript WinJS Promise progress函数未执行

Javascript WinJS Promise progress函数未执行,javascript,windows-8,windows-store-apps,winjs,promise,Javascript,Windows 8,Windows Store Apps,Winjs,Promise,我正在尝试创建一个基本承诺,其进度函数如下: asyncCall().then(function () { that.output("complete"); }, null, function(v) { that.output(v); }).done(); function asyncC

我正在尝试创建一个基本承诺,其进度函数如下:

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) {

你知道我在处理进度事件时遗漏了什么吗?

现在发生的是,你对progress()的调用与新WinJS.Promise的创建同步进行。也就是说,WinJS.Promise类被实例化,并且作为其初始化的一部分,它使用我所称的完整、错误和进度调度器调用您的匿名初始化器

这些分派器各自管理一个附加到它们的处理程序数组(“侦听器”),因此,当您调用它们时,就像您使用progress()和complete()所做的那样,它们会遍历该数组并依次调用每个处理程序

然而,在执行的这一点上,由于asyncCall尚未返回,并且事实上,新的WinJS.Promise尚未返回,所以没有任何处理程序被附加到任何对象。因此,您的呼叫进程(“某些进程”)发生得很好,但调度程序没有附加的处理程序,因此不会发生任何事情

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

简而言之,您的进度处理程序永远不会被调用,因为您的承诺初始值设定项正在与承诺的创建同步调用它。尝试在初始值设定项中执行以下操作:

setTimeout(function () {
   progress("some progress");
}, 100);
这也将产生收益,使您脱离承诺创建,这样您的进度处理程序将被附加。您还可以执行setInterval以每100ms调用一次progress,确保在发生1s完成超时时取消该间隔。然后您会看到对进度处理程序的重复调用


底线是,在承诺初始值设定项中对complete、error或progress的任何同步调用都不会影响传递给then的处理程序,因为then不会被调用。

发生的是,对progress()的调用与新WinJS.promise的创建同步进行。也就是说,WinJS.Promise类被实例化,并且作为其初始化的一部分,它使用我所称的完整、错误和进度调度器调用您的匿名初始化器

这些分派器各自管理一个附加到它们的处理程序数组(“侦听器”),因此,当您调用它们时,就像您使用progress()和complete()所做的那样,它们会遍历该数组并依次调用每个处理程序

然而,在执行的这一点上,由于asyncCall尚未返回,并且事实上,新的WinJS.Promise尚未返回,所以没有任何处理程序被附加到任何对象。因此,您的呼叫进程(“某些进程”)发生得很好,但调度程序没有附加的处理程序,因此不会发生任何事情

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

简而言之,您的进度处理程序永远不会被调用,因为您的承诺初始值设定项正在与承诺的创建同步调用它。尝试在初始值设定项中执行以下操作:

setTimeout(function () {
   progress("some progress");
}, 100);
这也将产生收益,使您脱离承诺创建,这样您的进度处理程序将被附加。您还可以执行setInterval以每100ms调用一次progress,确保在发生1s完成超时时取消该间隔。然后您会看到对进度处理程序的重复调用


底线是,在承诺初始值设定项中对complete、error或progress的任何同步调用都不会影响传递给then的处理程序,因为then不会被调用。

它实际上按照设计工作,但不一定按照预期工作。将为所有当前侦听器调用
进度
。但是,由于您的方法是完全同步的,因此在进行第一次调用时没有连接侦听器。与其他Promise功能不同,这有点不同,因为其他功能(如complete和error)仍然可以调用

如果包装asyncCall代码,您会看到这一点:

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

}

它实际上按设计工作,但不一定按预期工作。将为所有当前侦听器调用
进度
。但是,由于您的方法是完全同步的,因此在进行第一次调用时没有连接侦听器。与其他Promise功能不同,这有点不同,因为其他功能(如complete和error)仍然可以调用

如果包装asyncCall代码,您会看到这一点:

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

}

进度
通知应该会丢失,但是如果您不能在同一轮构造中调用
完成
错误
,这是一个错误,应该报告。感谢您的详细解释,但另一个答案提供了一个完整的解决方案,使代码按预期工作+1ing.您可以在构造过程中调用complete或error,但当时没有人在侦听,因此这只是一个no-op。这与在任何其他代码有机会附加处理程序之前让任何其他对象在构造过程中尝试引发事件相比,都不是一个bug。承诺比任何东西都更具号召力,因此美国