2013-05-30 47 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' 
}); 

現在我們拋出並正確處理承諾錯誤,承諾失敗意味着要處理。