4

我有一个简单的 angularjs 服务,它封装了微风,使其可用于我的应用程序。在此服务中,我希望有一个处理失败的单一机制。我试图在通话结束时将 .fail() 链接起来,如果微风通话失败(例如由于用户被注销),则会调用失败。唯一的问题是链中的第一个 .done() (通常位于调用服务的控制器中)也被调用。我只希望在微风成功时调用它。

如何防止第一个 done 也被调用?

以下是一个示例保存调用(使用 done 被错误调用)

dataStore.saveEntity(model)
    .then(function() {
    // This is being called on fail             
});

以及服务包装微风的片段

angular.module('app')
.factory('dataStore' ,function() {

        var _handleFail = function(error) {
            if (error && error.status && error.status === 401) {
                // Logged out error (for example

            }
        };



        function saveEntity(entity) {   
           return manager.saveChanges(entity).fail(_handleFail);    
        }
4

3 回答 3

3

事实证明 .fail() 进一步传播了承诺。考虑以下:

promise.then(function(){
      console.log('Then 1');
      throw new Error('Error');
  })
  .then(function(){
      console.log('Then 2');
  })
  .then(function(){
      console.log('Then 3');   
  })
  .fail(function(){
      console.log('Fail 1');   
  })
  .then(function(){
      console.log('Then 4');
  });

将输出:

> Then 1
> Fail 1
> Then 4

.fail() 从第一个 .then() 捕获错误,然后将 promise 传递给第四个 .then()。在我的示例中,微风查询生成一个错误,该错误被 .fail() 捕获,处理完毕后,promise 被移交给调用容器中的 .then()。

为了解决这个问题,_handleFail() 函数需要抛出一个错误,以防止任何链接的 .then() 被调用(直到错误再次由 .fail() 处理。

所以我的服务现在看起来像:

angular.module('app') .factory('dataStore' ,function() {

    var _handleFail = function(error) {
        if (error && error.status && error.status === 401) {
            // Logged out error (for example
            throw new Error('Unauthorized');
        }
    };



    function saveEntity(entity) {   
       return manager.saveChanges(entity).fail(_handleFail);    
    }
于 2013-09-18T12:04:07.067 回答
0

Jay 的回答是我所想的方向,我不能 100% 确定你将如何使用 Angular 的绑定对象来做到这一点,但是如果你不能改变结构,另一种选择是传递一个状态对象来跟踪失败链中的条件(该示例使用 Knockout observable,因为我不熟悉如何传递 Angular 正在观察的对象,但一般理论应该坚持) -

var status = ko.observable(true);    
// var $scope.status = true (maybe???)
dataStore.saveEntity(model)
    .then(function() {
        if (status()) { // status still equals true, no failures occurred, carry on 
        }
});


angular.module('app')
.factory('dataStore' ,function() {
    var _handleFail = function(error) {
        if (error && error.status && error.status === 401) {
            // Logged out error (for example)
            status(false);
        }
    };

    function saveEntity(entity) {   
       return manager.saveChanges(entity).fail(_handleFail);    
    }

fail() 应该在 then() 在您的控制器中执行之前触发,并且当到达 then() 逻辑时,它将知道链上存在问题。

于 2013-09-17T23:02:46.553 回答
0

我实际上还没有看到任何例子,在你正在做的'then'之前在promise链上调用'fail'。所以我会尝试重写你的代码看起来像:

function handleFail(error) {
    if (error && error.status && error.status === 401) {
        // Logged out error (for example

    }
};


dataStore.saveEntity(model)
 .then(function() {
    // your success code here. - should not get called except on success.
 }).fail(handleFail);

以及服务包装微风的片段

angular.module('app')
   .factory('dataStore' ,function() {

        function saveEntity(entity) {   
           return manager.saveChanges(entity);
        }
    });

可能还有其他方法,但这似乎最简单。

于 2013-09-17T22:29:53.580 回答