2015-07-03 60 views
1

(這不是JavaScript closure inside loops – simple practical example的重複,因爲你不能選擇catch函數採用哪個參數)node.js承諾:如何找出哪個迭代拋出.catch語句中的異常?

我是新來的Node.js的異步回調性質。我試圖找出for循環中的哪個元素拋出異常。

當前代碼總是返回數組中的最後一個元素,而不管哪個元素拋出異常。

for (i = 0; i < output.length; i++) { 
    var entity = Structure.model(entity_type)[1].forge(); 

    /* do some stuff here which I've taken out to simplify */ 

    entity.save() 
     .then(function(entity) { 
      console.log('We have saved the entity'); 
      console.log(entity); 
      returnObj.import_count++; 
     }) 
     .catch(function(error) { 
      console.log('There was an error: ' + error); 
      console.log('value of entity: ', entity); /* THIS entity variable is wrong */ 
      returnObj.error = true; 
      returnObj.error_count++; 
      returnObj.error_items.push(error); 
     }) 
     .finally(function() { 
      returnObj.total_count++; 
      if (returnObj.total_count >= output.length) { 
       console.log('We have reached the end. Signing out'); 
       console.log(returnObj); 
       return returnObj; 
      } else { 
       console.log('Finished processing ' + returnObj.total_count + ' of ' + output.length); 
      } 
     }) 
} 

我怎麼寫,讓我訪問拋出異常,所以我可以將其存儲在有問題的元素列表元素的方式承諾?

+0

你是什麼意思返回最後一個元素? – thefourtheye

+0

我的意思是,在遍歷30個元素之後,它總是返回元素30,而不是導致異常的元素(例如15)。 – TheBarnacle

+0

如果你不認爲它是重複的,請參考[臭名昭着的循環問題](http://stackoverflow.com/q/1451009/1048572)。這完全是同一個問題 - 你不必選擇'catch'或'onclick'或其他回調所需的參數。 – Bergi

回答

1

發生這種情況是因爲傳遞給catch的匿名函數只能通過閉包訪問entity

如果實體是原始類型,可以通過構造一個通過參數(其中entity的值將被複制構建時間)捕獲該值的新函數輕鬆解決這個問題。

.catch(function(entity){ 
    return function(error) { 
     console.log('There was an error: ' + error); 
     console.log('value of entity: ', entity); /* THIS entity variable is wrong */ 
     returnObj.error = true; 
     returnObj.error_count++; 
     returnObj.error_items.push(error); 
    }; 
}(entity)) 

(請注意,我立即與()調用該函數,所以抓只接收返回的函數作爲參數)

如果實體爲對象(只按引用傳遞),你可以使用相同的基本原則,但您必須創建此實體的副本,這會稍微複雜一些。在這種情況下,如果你使用原始的i(作爲一個原始類型,它很容易用上面的方法捕獲)編寫錯誤處理程序,或者如果你不在循環中重用實體變量,可能會更容易。

順便說一句,你確定var entity = Structure.model(entity_type)[1].forge(); - >這裏1不應該是i

+0

感謝您的支持!你的意思是我應該寫.catch(function(i){}())?我不知道參數名稱可能會引用現有變量。我認爲函數(variableName)剛在新的作用域中實例化了一個新變量。 – TheBarnacle

+0

噢 - [1]是故意的 - 我也許應該把它留下來,因爲它指的是程序中的其他地方。而「實體」是一個對象,這就是爲什麼我需要考慮你的第二個解決方案。 – TheBarnacle

+0

是的,我的意思是。如果一個參數名稱引用了一個現有的變量,它將* shadow *它,這意味着在該函數內通過該名稱只能引用該參數。 (這是一個非常普遍的概念,不是特定於JavaScript的,雖然它經常會在關閉時發揮作用) – doldt