Angularjs 承诺拒绝链

Posted

技术标签:

【中文标题】Angularjs 承诺拒绝链【英文标题】:Angularjs promise rejection chaining 【发布时间】: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中抛出异常来完成,但是它将异常跟踪写入控制台,这不好。

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

【问题讨论】:

【参考方案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);解决了这个问题。 :) 无论如何谢谢。

以上是关于Angularjs 承诺拒绝链的主要内容,如果未能解决你的问题,请参考以下文章

在 angularjs 拦截器中停止请求

AngularJS 资源承诺

使用 AngularJS 立即返回一个已解决的承诺

AngularJS 中的链式承诺

AngularJS 测试 - 来自服务的承诺无法解决

AngularJS 承诺处理 CoffeeScript 类