6

给定以下两个$resource示例:

var exampleOne = $resource('/path').save(objectOne);
exampleOne.$promise.then(function (success) {}, function (error) {});

var exampleTwo = $resource('/path').save(objectTwo);
exampleTwo.$promise.then(function (success) {});

[注意:示例 2 不包含错误处理程序]

还有一个位于所有$http请求下方的拦截​​器:

var interceptor = ['$location', '$q', function ($location, $q) {
   function error(response) {
       if (response.status === 400) {
           return $q.reject(response);
       }
       else {
           $location.path('/error/page');
       }
       return $q.reject(response);
   }

   return {
       'responseError': error
   };
}

$httpProvider.interceptors.push(interceptor);

$promise.then()当示例资源不包含错误回调时,如何使拦截器不拒绝?如果回调存在,exampleOne那么我希望拒绝,但如果不存在,exampleTwo那么我希望重定向到错误页面,从而将条件更改为:

if (response.status === 400 && $q.unresolvedPromises.doIndeedExist()) { ...

为什么?因为我的项目中只有某些情况需要400以用户友好的方式处理,因此我想消除许多重复的错误回调或不得不在拦截器中放置一个不常见情况的列表。我希望拦截器能够根据承诺链中另一个处理程序的存在做出决定。

4

2 回答 2

2

简而言之,这是不可能的,您无法检测到将来是否有人会附加处理程序,就像您无法判断何时throw在函数中它是否会被外部捕获一样。不过,你想做的事都可以做到

这不是一个“菜鸟问题”,而是非常基本的:

 function foo()
    throw new Error(); // I want to know if whoever is calling `foo`
                       // handles this error
 }

首先,你能做什么

简单的说第一种情况:

 exampleOne.$promise.then(function (success) {}, function (error) {});

你得到的是一个永远兑现的承诺。但是,在第二种情况下,promise 可能会被拒绝。使用拒绝处理程序处理拒绝就像catch实际代码一样 - 一旦处理它,它就不再被拒绝。

就个人而言,我不会在这里使用拦截器,而是使用资源使用模式,因为它的意图更清晰,你可以将它包装在一个函数中,这样它就不需要范围,但我不太喜欢这个想法。这是我要做的

attempt(function(){
    return $resource('/path').save(objectTwo).$promise.
           then(function (success) {});
});

function attempt(fn){
    var res = fn();
    res.catch(function(err){
        // figure out what conditions you want here
        // if the promise is rejected. In your case check for http errors
        showModalScreen();
    }
    return res; // for chaining, catch handlers can still be added in the future, so
                // this only detects `catch` on the function passed directly so 
                // we keep composability
}

现在,一个简短的证明,它不能完成

让我们证明它的乐趣。

假设给定程序 M 的代码,我们创建一个新的 Promisep并将 M 中的每个return语句和 Mthrow中的语句替换为 areturn p.catch(function(){})并添加 a ,现在当且仅当运行终止return p.catch(function(){})时才会添加处理程序。因此,简而言之,给定代码 M,我们构建了一种方法来查看它是否会根据存在的解决方案来判断它是否停止,该解决方案可以解决查找是否附加到的问题- 所以这个问题至少与停止问题一样难。pMcatchp

于 2014-08-13T20:56:34.243 回答
0

也许您可以以零超时推迟重定向,并给错误处理程序一个机会(如果存在)在错误处理的错误对象上设置标志:

var interceptor = ['$q', '$timeout', function ($q, $timeout) {
    function error(rejection) {

            return $q.reject(rejection).finally(function () {
                $timeout(function () {
                    if (rejection.errorHandled === true) {
                        alert('all is under control');
                    } else {
                        alert("Houston we've got problems");
                    }
                }, 0); //zero timeout to execute function after all handlers in chain completed
            });
    }

    return {
        'responseError': error
    };
}];

var exampleOne = $resource('/path').save(objectOne);
exampleOne.$promise.then(function (success) { }, function(error) {
    error.errorHandled = true;
});
于 2014-08-13T21:12:17.240 回答