如何在拦截器模式中使用dojo / promise / Promise.cancel()

时间:2013-04-17 19:01:50

标签: javascript dojo

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

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

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

    提前致谢!

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

    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;
            }
        )
    );
    

1 个答案:

答案 0 :(得分:5)

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

promise.then(successCallback, errorCallback)

  • 返回一个承诺。
  • 如果符合以下条件,这个承诺就会得到解决(成功):
  • successCallback errorCallback返回一个值。使用此值解析promise,或者如果此值是promise,则使用此promise的解析来解析。

  • 如果符合以下条件,则此承诺会被拒绝(错误):

  • successCallback errorCallback会抛出错误。

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

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方法中放置逻辑,以区分已取消的请求和错误。

不幸的是,你不允许停止链接,承诺旨在强有力地传递给完成。但是,您可以在每个交叉点放置一个错误,只在您真正需要时添加一个错误,并且您的解决方案应该非常干净。