2016-09-30 24 views
0

我有這樣的設計:遞延鏈接,Node.js和受Q,所有鏈部分一個單一的ErrorHandler

var postCommand = function(req, res){  
    parseForm(req) 
    .then(checkData) 
    .then(findCommand) 
    .then(initializeCommand) 
    .then(saveToDb) 
    .then(onUploadSucceeded.bind(this, res)) 
    .fail(onUploadFailed.bind(this, res)); 
} 

中的那麼的有可能拒絕該方法。我希望在發生拒絕事件之後不再執行任何操作,但最後一次.fail。

我「checkData」看起來是這樣的(是啊,它的唯一的同步鏈中的一部分):

var checkData = function(args){ 
    var deferred = q.defer(); 
    var fields = args[0]; 
    var files = args[1]; 
    var file = args[1].uploadedFile0; 
    var secondFile = args[1].uploadedFile1;  
    if(file.type !== "application/javascript"){ 
     return deferred.reject("please only upload javascript-files"); 
    } 
    (...) 
    return deferred.resolve([fields, file]); 
} 

即使deferred.reject被調用時,我在「findCommand」最終沒有傳遞的參數。我是否理解這個鏈條有什麼問題?

另外的問題:這個設計是一個很好的模式?還是有其他更好的最佳做法?

+0

你真的應該做的每'然後內響應驗證(... )'你的承諾聲明。如果迴應不包含預期的內容,那麼你打破承諾鏈。 –

+0

但每個失敗的回調都會做同樣的事情......調用「onUploadFailed」並將錯誤傳遞給拒絕。這對我來說就像代碼複製一樣,並降低了可讀性。我想拋出一個豁免而不是拒絕,因爲q文檔說「catch」方法會捕獲上述鏈的任何錯誤。但是,這似乎有點臭 – IntegerWolf

+2

我使用藍鳥,所以我不知道,但我認爲你應該在所有情況下返回deferred.promise。 – Keith

回答

2

如果checkData()是在承諾鏈的開始的話,那就需要在own answer被寫成,返回一個明確的承諾。

在中間鏈它也會工作時,這樣寫,但中鏈給你更好的選擇寫什麼。

更具體地說,你可以不用創建並返回一個承諾:

  • 拋出而不是返回被拒絕的承諾,
  • 承諾包裹的數據,而不是返回的數據。

因此,提供checkData()從未在其他地方用來啓動一個承諾鏈,它可以被寫成這樣:

var checkData = function(args) { 
    var fields = args[0], 
     files = args[1], 
     file = args[1].uploadedFile0, 
     secondFile = args[1].uploadedFile1;  
    if(file.type !== "application/javascript") { 
     throw new Error("please only upload javascript-files"); // always throw an Error object, thus emulating a natural Error. This error will percolate down to the `.fail(onUploadFailed.bind(this, res))` handler. 
    } 
    (...) 
    return [fields, file]; // the next step in the chain will assimilate a promise or data. 
} 
0

正如他的評論勸由Keith這是一個語法問題,解決方法:

var checkData = function(args){ 
    var deferred = q.defer(); 
    var fields = args[0]; 
    var files = args[1]; 
    var file = args[1].uploadedFile0; 
    var secondFile = args[1].uploadedFile1;  
    if(file.type !== "application/javascript"){ 
     deferred.reject("please only upload javascript-files"); 
    } 
    else{ 
     deferred.resolve([fields, file]); 
    }   
    return deferred.promise; 
} 
+0

鑑於函數是同步的,你根本不應該使用延遲。使用'Q' /'Q.reject'來創建履行/拒絕的承諾,或者只是'return'和'throw',當'checkData'被用作'then'處理函數時具有相同的效果。 – Bergi