【问题标题】:WinJS Promise progress function does not get executedWinJS Promise 进度函数未执行
【发布时间】:2023-04-08 21:30:01
【问题描述】:

我正在尝试创建一个带有进度功能的基本承诺,例如:

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

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

【问题讨论】:

    标签: javascript windows-8 windows-store-apps winjs promise


    【解决方案1】:

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

    如果你包装了你的 asyncCall 代码,你会看到这个:

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

    【讨论】:

      【解决方案2】:

      正在发生的事情是,您对 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 不会被调用。

      【讨论】:

      • progress 通知应该会丢失,但是如果您不能在同一轮构造中调用completeerror,这是一个错误,应该报告。
      • 感谢您的详尽解释,但另一个答案提供了一个完整的解决方案,使代码按预期工作。 +1。
      • 您可以在构建过程中调用完成或错误,但当时没有人在听,所以它只是一个空操作。这与在任何其他代码有机会附加处理程序之前让任何其他对象在构造期间尝试引发事件相比,这不是一个错误。 Promise 是一个调用构造,因此一旦构造完成就完成 Promise 的有用性是值得怀疑的——为什么不只是有一个返回值的函数呢?另外,如果你需要一个固定值的 Promise,请使用 WinJS.Promise.as,这要简单得多。
      猜你喜欢
      • 1970-01-01
      • 2019-04-17
      • 2019-08-30
      • 1970-01-01
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      • 2017-08-04
      • 2015-08-07
      相关资源
      最近更新 更多