AngularJS承诺拒绝链接

30

我需要创建链式Promises:

var deferred = $q.defer();
$timeout(function() {
    deferred.reject({result: 'errror'});
}, 3000);
deferred.promise.then(angular.noop, function errorHandler(result) {
    //some actions
    return result;
}).then(function successCallback(result) {
    console.log('what do I do here?');
    return result;
}, function errorCallback(result) {
   $scope.result= result;
   return result;
});

如果我把一个错误回调函数放在第一个then里,第二个then将会被解决并且它的成功回调函数将会被调用。但是如果我移除errorHandler,那么第二个promise将会被拒绝。

根据Angular JS文档,唯一传播拒绝的方法是返回$q.reject();,但这看起来不太明显,特别是因为我必须注入$q服务,即使它没有被使用;

还可以通过在errorHandler中抛出异常来实现,但它会将异常跟踪写入控制台,这不好。

有没有其他的清晰方式来做到这一点?原因是什么?在哪种情况下,当前行为可能是有用的?

2个回答

68

为什么要这样做?在哪些情况下,当前行为可能是有用的?

当你想在错误处理程序中尝试修复错误状态并以某种方式解决 Promise 时,它可能是有用的。

var retriesCount = 0;

function doWork()
{
    return $http.post('url')
        .then(function(response){
            // check success-property of returned data
            if(response.data.success)
                // just unwrap data from response, may be do some other manipulations
                return response.data;
            else
                // reject with error
                return $q.reject('some error occured');
        })
        .catch(function(reason){
            if(retriesCount++ < 3)
                // some error, let me try to recover myself once again
                return doWork();
            else
                // mission failed... finally reject
                return $q.reject(reason);
        });
}


doWork().then(console.log, console.error);

12
请使用.catch(function(){})代替.then(null, function(){}) - Dinistro
我点了赞,但我同意@Dinistro的观点,你需要在这里使用正确的语法,并在.catch方法中捕获Promise拒绝。这是处理被拒绝的Promise的最佳方式。 - Sten Muchow

5

虽然我来晚了,但既然在这里;

与返回200并在响应中返回错误状态相比,我更喜欢使用$http错误进行原生错误处理。

如果您正在调试,将400500错误打印到控制台是没有问题的,如果您不需要,则不会看到它们。

angular.module('workModule', [])

// work provider handles all api calls to get work
.service('workProvider', ['$http', '$q', function($http, $q) {

    var endpoint = '/api/v1/work/';

    this.Get = function(){
        // return the promise, and use 404, 500, etc for errors on the server
        return $http.get(endpoint);
    };

}])

.controller('workController', ['workProvider', function('workProvider'){

    workProvider.Get().then(
        function(response){ // success
            console.log(response.data);
        },
        function(response){ // error
             console.log(response.data);           
        }
    )

}])

同意 - 服务器只有在操作成功时才应返回200。这对系统监控和日志记录有影响(错误被掩盖在200响应中)。唯一的例外是数据验证(如果向客户端返回200并提供如何修复的响应,则可以发送不正确的数据以进行有效的用户流程)。 - voidsstr
我在服务中有以下代码:return $http.get(endpoint).then(function(response) { return response.data; }, function(error) { return error.data; })但是当发生错误时,数据被传递到成功回调函数(then() 中的第一个函数)而不是错误回调函数(then() 中的第二个函数)。我尝试返回 $q.reject(error.data) 而不是 error.data,但是没有起作用。为什么会发生这种情况? - Alejandro Sanz Díaz
1
@AlejandroSanzDíaz,“Error”发生在哪里?这是一个响应吗?如果是,你的“Error”的响应代码是什么?200 = 成功,4XX或5XX将导致错误。还要检查$http文档,尽量不使用then而是使用successerror回调函数。如果是这种情况,我会进行编辑。 - Matthew.Lothian
4
我最终通过在errorCallback函数内使用 return $q.reject(error.data); 解决了它。 :) 无论如何还是要谢谢你。 - Alejandro Sanz Díaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接