【问题标题】:How to find out if WinJS.Promise was cancelled by timeout or cancel() call如何确定 WinJS.Promise 是否被超时或 cancel() 调用取消
【发布时间】:2015-04-14 23:34:45
【问题描述】:

我有一个包含在超时承诺中的服务器请求。

var pendingRequest = WinJS.Promise.timeout(5000, requestAsync).

用户在 UI 上还有一个“取消”按钮,可以通过执行pendingRequest.cancel() 来主动取消请求。但是,无法查明承诺是否已被用户或超时取消(因为 timeout 在内部也调用了promise.cancel())。

如果 WinJS.Promise.timeout 使用不同的 Error 对象(如“Timeout”而不是“Canceled”)移动处于错误状态的 Promise,那就太好了。

知道如何确定请求是否已因超时取消?

更新:这个解决方案怎么样:

(function (P) {
        var oldTimeout = P.timeout
        P.timeout = function (t, promise) {
            var timeoutPromise = oldTimeout(t);
            if (promise) {
                return new WinJS.Promise(function (c, e, p) {
                    promise.then(c,e,p);
                    timeoutPromise.then(function () {
                        e(new WinJS.ErrorFromName("Timeout", "Timeout reached after " + t + "ms"));
                    });
                });
            } else {
                return timeoutPromise;
            }
        };
    })(WinJS.Promise);

【问题讨论】:

    标签: javascript promise winjs cancellation


    【解决方案1】:

    根据the documentation

    ...promise 进入错误状态,值为 Error("Canceled")

    因此,error.message === 'Canceled' 可以在您的错误处理程序中检测到。

    此外,WinJS.Promise 允许在构造时指定 onCancel 回调。

    var promise = new WinJS.Promise(init, onCancel);
    

    其中initonCancel 都是函数。

    Here's a demo.

    编辑

    啊,好的,抱歉我看错了这个问题。我现在了解到您希望区分超时和手动取消的承诺。

    是的,可以通过向双方提供适当的消息来完成:

    • WinJS 承诺的 onCancel 回调
    • 链式“catch”回调。

    首先,用 .timeout() 方法扩展 WinJS.Promise.prototype:

    (function(P) {
        P.prototype.timeout = function (t) {
            var promise = this;
            promise.message = 'Canceled';
            P.timeout(t).then(function() {
                promise.message = 'Timeout';
                promise.cancel();
            });
            return promise.then(null, function() {
                if(error.message == 'Canceled') {
                    throw new Error(promise.message); //This allows a chained "catch" to see "Canceled" or "Timeout" as its e.message.
                } else {
                    throw error; //This allows a chained "catch" to see a naturally occurring message as its e.message.
                }
            });
        };
    })(WinJS.Promise);
    

    这成为每个WinJS.Promise()实例的方法,因此与静态方法WinJS.Promise.timeout()不冲突。

    现在,使用.timeout() 方法如下:

    function init() {
        //whatever ...
    }
    
    function onCancel() {
        console.log('onCacnel handler: ' + this.message || `Canceled`);
    }
    
    var promise = new WinJS.Promise(init, onCancel);
    
    promise.timeout(3000).then(null, function(error) {
        console.log('chained catch handler: ' + error.message);
    });
    
    promise.cancel();
    /* 
     * With `promise.cancel()` uncommented, `this.message` and `error.message` will be "Canceled".
     * With `promise.cancel()` commented out, `this.message` and `error.message` will be "Timeout".
     */
    

    Demo(带有额外的按钮动画代码)。

    【讨论】:

    • 我知道。这就是 问题。无法知道该承诺是被timeout 取消,还是被超时承诺以外的其他人调用cancel 取消。
    • @philk 只是...滚动你自己的.timeout?
    • @Roamer-1888 感谢这个版本!我有refined 一点。现在它支持正确的错误链接和正常完成的承诺。此外,当实际的承诺完成(成功或错误)时,超时承诺现在被取消。你怎么看?
    • (1) 我不认为.wrapError() 是必要的。 WinJS 承诺是抛出安全的。如果不是,我的演示将不会将抛出的错误传递到错误路径中。 (2) 取消超时承诺(在两个地方)没有害处,但没有必要,因为如果promise 已经以任何方式解决,promise.cancel() 将什么也不做。一旦确定,promise 的状态就是不可变的。
    • (3) 您发现了我的版本中最糟糕的方面 - 即出于任何其他原因(既不是超时也不是手动取消)的拒绝将被表示为“已取消”。我的修改与你的略有不同(见编辑后的答案)。
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-01
    相关资源
    最近更新 更多