【问题标题】:Angularjs promise rejection chainingAngularjs 承诺拒绝链
【发布时间】:2013-09-16 11:21:44
【问题描述】:

我需要创建链式承诺:

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

如果我将errorCallback 放入第一个then,第二个then 将被解析并调用它的successCallback。但是如果我删除errorHandler,那么第二个承诺将被拒绝。

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

也可以通过在errorHandler中抛出异常来完成,但是它将异常跟踪写入控制台,这不好。

是否有另一种方法可以明确地做到这一点?原因是什么?为什么要完成?在哪种情况下,当前行为可能有用?

【问题讨论】:

    标签: javascript angularjs promise


    【解决方案1】:

    以及这样做的原因是什么。在哪种情况下,当前行为可能有用?

    当您在 errorHandler 中尝试修复错误状态并以某种方式解决承诺时,它会很有用。

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

    【讨论】:

    • 注意:你可以用.catch(function(){})代替.then(null, function(){})
    • 我投了赞成票,但我同意@Dinistro,您需要在这里使用正确的语法并在 .catch 方法中捕获承诺拒绝。这是处理被拒绝的承诺的方式。
    【解决方案2】:

    聚会迟到了,但因为我在这里;

    我更喜欢使用$http 错误来处理其本机错误,而不是通过200 返回成功并在响应中返回错误状态。

    在控制台中打印 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 可以返回给客户端,如果它是一个有效的用户流来发送不正确的数据并响应如何修复)。
    • 我在服务中有以下内容:return $http.get(endpoint).then(function(response) { return response.data; }, function(error) { return error.data; }) 但是当发生错误时,数据将传递给 successCallback(then() 中的第一个函数)而不是 errorCallback(then() 中的第二个函数)。我尝试返回 $q.reject(error.data) 而不是返回 error.data,但不起作用。为什么会这样?
    • @AlejandroSanzDíaz “错误”发生在哪里?这是回应吗?如果是这样,您的“错误”的响应代码是什么。 200 = 成功,4XX 或 5XX 将导致错误。还要检查$http 的文档,尽量不要使用then 而不是successerror 回调。如果是这种情况,我会编辑。
    • 我终于在errorCallback函数中使用return $q.reject(error.data);解决了这个问题。 :) 无论如何谢谢。
    猜你喜欢
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多