2013-05-30 44 views
8

我试图想出一个好办法,说:“做所有这些事情,但保释在其中的任何失败的情况下”停止一个AngularJS承诺链

我有什么权利现在:

var defer = $q.defer(); 

this 
    .load(thingy) // returns a promise 

    .then(this.doSomethingA.bind(this)) 
    .then(this.doSomethingB.bind(this)) 
    .then(this.doSomethingC.bind(this)) 
    .then(this.doSomethingD.bind(this)) 

    .then(function(){ 
     defer.resolve(this); 
    }); 
    ; 

return defer.promise; 

我最终想要以某种方式捕捉该链上的任何错误,以便我可以将它传递给上面的defer承诺。我并不特别在乎语法是否与上面的类似。

或即使任何人都可以告诉我如何停止上述链。

+1

@ user2246674 - 拒绝它似乎并没有停止链,但下一个只是继续 –

+1

不知道我在想什么.. – user2246674

+2

这是[deferred antipattern](http: //stackoverflow.com/q/23803743/1048572)! (推迟),只是'返回'this.load(...)。然后(A)。然后(B)。然后(C)。然后(D);'链! – Bergi

回答

2

你应该能够做到同样的事情:

var defer = $q.defer(); 

this 
    .load(thingy) // returns a promise 

    .then(this.doSomethingA.bind(this), $q.reject) 
    .then(this.doSomethingB.bind(this), $q.reject) 
    .then(this.doSomethingC.bind(this), $q.reject) 
    .then(this.doSomethingD.bind(this), $q.reject) 

    .then(defer.resolve.bind(defer, this), defer.reject.bind(defer)); 
    ; 

return defer.promise; 
+3

此答案使用反模式并导致用户重复错误处理。 –

0

好吧,这工作,但我不喜欢它...等待更好的东西:)

这似乎只是脏创建立刻拒绝它

myApp 
    .factory('chainReject', [ '$q', function($q){ 
     return function(err){ 
      var defer = $q.defer(); 
      defer.reject(err); 

      return defer.promise; 
     } 
    } ]); 

... 

var defer = $q.defer(); 

this 
    .load(thingy) // returns a promise 

    .then(this.doSomethingA.bind(this), chainReject) 
    .then(this.doSomethingB.bind(this), chainReject) 
    .then(this.doSomethingC.bind(this), chainReject) 
    .then(this.doSomethingD.bind(this), chainReject) 

    .then(defer.resolve.bind(defer, this), defer.reject.bind(defer)); 
    ; 

return defer.promise; 
5

您可以通过在任何回调中返回被拒绝的承诺来阻止angularjs链。

load() 
.then(doA) 
.then(doB) 
.then(doC) 
.then(doD); 

其中DOADOBDOC国防部可以有逻辑是这样的:

var doA = function() { 
    if(shouldFail) { 
     return $q.reject(); 
    } 
} 
+1

+1这对我来说是'return $ q.reject()'的'return'部分。许多搜索导致各种不同的方式,但实际上返回$ q。拒绝()而不是仅仅调用它实际上是杀死链条。特别是如果你正在尝试做一些不是HTTP失败的事情,而是在模型返回一个预期的否定响应的意义上的'失败'。 – coblr

+0

阻止链条的另一种方式,假设你想显示链条执行过程中发生的错误,你可以'抛出新的Error()' –

+0

返回被拒绝的promise不会阻止链条。 – user3631341

3

我只是碰到这种迷迷糊糊地意识到所有这些答案都非常过时。对于任何碰巧找到这篇文章的人来说,这是处理这个问题的正确方法。

// Older code 
return this.load(thing) 
    .then(this.doA, $q.reject) 
    .then(this.doB, $q.reject) 
    .then(this.doC, $q.reject) 
    .then(this.doD, $q.reject) 
    .then(null, $q.reject); 


// Updated code 
// Returns the final promise with the success handlers and a unified error handler 
return this.load(thing) 
    .then(this.doA) 
    .then(this.doB) 
    .then(this.doC) 
    .then(this.doD) 
    .catch(this.handleErrors); // Alternatively, this can be left off if you just need to reject the promise since the promise is already rejected. 
    // `.catch` is an alias for `.then(null, this.handleErrors);` 
+0

当问这个问题时''catch'不存在于'$ q'的角度:) –

+0

@zyklus,你是正确的,但'.catch'只是'.then(null,fn)'的别名。那应该是有效的。 –

+0

它并没有用来传递错误,也就是只能捕获前一个'then'的错误,这就是为什么我在下面写下所有链式拒绝废话的原因。 –

0

处理这个问题和解决问题的最好方法是.catch块。里面,你想杀死承诺链中的任何块。那么,是使用:

return $q.reject(); 

但是扩展它是这样的...

return $q.reject(new Error('Error Message Here')); 

现在在catch方法,你就会有这种

.catch(function(err) { 
    console.log(err); //This will log the above 'Error Message Here' 
}); 

现在我们抛出并正确处理承诺错误,承诺失败意味着要处理。