4

我希望为特定于应用程序的 AJAX 控制器实现一个 Inteceptor Pattern。

我的应用程序中的任何 AJAX 请求都会调用 Authenticator.request(),它会拦截响应,检查某些状态(例如 401、403、503),根据它们执行特定于应用程序的显示功能(即,如果状态 401 是,则显示 LoginDialog已收到)。我的问题源于对 dojo 的 Promises 的混淆。

  1. 如何将成功的请求传递回原始调用方法?
  2. 当我调用 dojo.promise.Promise.cancel() 时,我希望链接停止。但是,这只是运行 errback 函数。这意味着需要在调用函数的每个 errback 方法中放置逻辑,以区分取消的请求和错误。

谁能向我解释在这种情况下如何使用 Promises?

提前致谢!

这是我认为我可以做的一个例子......

require(["dojo/request"], function(request){
    auth = { 
        request: function() {
            var promise = request(arguments);

            return promise.always(function (response) {
                console.log("always called", response);
                switch (response.response.status)
                {
                    case 404:
                        console.log(404, response);
                        return "cancelled";
                        break;
                }
            });
        }
    };
});

auth.request('example.json').then(function(text){ console.log('success!', text) }, function(error){
    console.log('error!', error);
});

如果这对将来的任何人有帮助,这就是我最终实现的(基于戴夫的回答)......

require(["dojo/request", "dojo/errors/CancelError"], function(dRequest, CancelError){
    auth = { 
        request: function(url, options) {
            var promise = dRequest(url, options);

            return promise.response.then(
                function (response) {
                    return response;
                },
                function (error) {
                    var error,
                        cancelError = new CancelError(error.message);
                    cancelError.response = error.response;
                    console.log("error", error, cancelError);

                    switch (error.response.status)
                    {
                        case 404:
                            console.log(404, "canceled");
                            throw cancelError;
                    }
                    throw error;
                }
            );
        },
        cancelTrap: function (errorBack, cancelBack) {
            return function (error) {
                throw (error instanceof CancelError) 
                    ? cancelBack && cancelBack(error) || error 
                    : errorBack && errorBack(error) || error;
            }
        }
    };
});

...然后可以像这样使用...

r = auth.request('something.json');
r.then(
    function(text){
        console.log('success! > this', this)
        console.log('success!', text)
        return text;
    }, 
    auth.cancelTrap(
        function (error) {
            console.log('error!', error);
            throw error;
        },
        function (cancelError) {
            console.log('cancelError!', cancelError);
            throw cancelError;
        }
    )
).then(
    function(text){
        console.log('success2!', text)
    }, 
    auth.cancelTrap(
        function (error) {
            console.log('error2!', error);
            throw error;
        },
        function (cancelError) {
            console.log('cancelError2!', cancelError);
            throw cancelError;
        }
    )
);
4

1 回答 1

5

Promise 非常强大,我认为您应该尝试了解通过该then函数提供的两种执行路径(假设always只是使用then与两个参数相同的函数进行调用的快捷方式):

promise.then(successCallback, errorCallback)

  • 返回一个承诺。
  • 如果满足以下条件,则此承诺已解决(成功):
  • successCallbackerrorCallback 返回一个值。这个promise 要么用这个值解决,或者如果这个值是一个promise,它用这个promise 的resolve 来解决。

  • 如果出现以下情况,则此承诺被拒绝(错误):

  • successCallbackerrorCallback 都会引发错误。

此外,如果没有提供 errorCallback ,如果原始承诺被拒绝(错误),则会冒泡到提供错误处理程序的下一个级别,所以如果我这样做:

promise.then(func1).then(func3).then(finalFunc, errorHandler);
promise.reject(someError);

然后errorHandler用 调用someError

这一切的意思是,如果您不想在某个级别处理错误,那就不要,让它在链中冒泡并在最高级别实现一个错误处理程序。如果您只想处理某些错误,您可以像这样“包装它或捕获它”:

promise.then(successFunction, function(error) {
    if(error.code > 400) {
         // do something clever, maybe just send an empty result up the chain
         return []; // goes to successCallbacks!
    } else {
        throw error; // pass it to the next errorHandler
    }
});

最后,总结一下并尝试回答您的问题:

如何将成功的请求传递回原始调用方法?

您可以简单地return将值传递给下一个successHandler。

当我调用 dojo.promise.Promise.cancel() 时,我希望链接停止。但是,这只是运行 errback 函数。这意味着需要在调用函数的每个 errback 方法中放置逻辑,以区分取消的请求和错误。

不幸的是,您不允许停止链接,promise 旨在稳健地传递到完成。但是,您不能每个路口都放置一个错误提示,仅在您真正需要时添加一个,并且您的解决方案应该非常干净。

于 2013-04-18T09:38:15.717 回答