2016-09-05 21 views
2

我找不到上https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach任何暗示,但基本上我試圖做的事:刪除javascript映射的forEach循環中的條目是否安全?

sessions.forEach(function (session, id) { 
    someConditionReached(id, function(err, res)) { 
     if (shouldDelete(err, res)) { 
     sessions.delete(id); 
     } 
    } 
}); 

這會造成什麼麻煩嗎?如果是這樣,我應該做一個臨時數組來收集所有過時的會話,並在forEach之後刪除它們?問題是,循環中的條件是基於異步/回調的,因此執行延遲刪除會很麻煩。

+0

'sessions.delete()'是什麼? –

+1

@NinaScholz:這是從地圖中刪除條目的方法; http://www.ecma-international.org/ecma-262/7.0/index.html#sec-map.prototype.delete。 –

+0

我可以看到的唯一潛在的麻煩是您稍後(在循環之後,但在回調觸發之前)確定會話正在擴展(並且不應再被刪除)。但大概'shouldDelete'會照顧到這一點。 – Thilo

回答

2

你問

是安全的一個javascipt的地圖的foreach循環中刪除條目?

也說

問題是,在循環的條件是基於異步/回調,所以這將是繁瑣做延期刪除。

(謝謝你Thilo指出這一點時,我錯過了!)

這意味着你是forEach期間刪除。這些回調不會發生,直到forEach完成後。例如,它們已經被延期。因此,問題「刪除javascipt映射的forEach循環中的條目是否安全?」不適用,因爲你沒有這樣做。由於Thilo points out in a comment,唯一真正關心的是id是否仍然是您刪除內容的合法標識符,以及刪除是否仍然適用(在這兩種情況下,大概都是這樣,但值得注意)。


但在標題回答這個問題(對於未來的讀者),讓我們變更碼了一點,所以它不是後來做的缺失異步回調:

sessions.forEach(function(session, id) { 
    if (shouldDelete(session)) { 
     sessions.delete(id); 
    } 
}); 

當MDN讓你失望,轉到the specification

地圖的[[MapData]]的每個條目只訪問一次。在forEach電話開始之後添加的新鍵被訪問。如果密鑰在訪問後被刪除,並且在forEach呼叫完成之前重新添加,該密鑰將被重新訪問。 除非在forEach呼叫完成之前再次添加密鑰,否則不會訪問在forEach呼叫開始之前和被訪問之前刪除的密鑰。

(我的重點)

的強調一點清楚的是,forEach中刪除是沒有問題的。

+2

請注意,在執行任何刪除調用之前,這裏的forEach將完成(因爲它們都發生在回調中)。因此,在建立要刪除的密鑰集(以及'forEach'不會影響密鑰集之後發生的任何事情)期間,不會添加或刪除任何內容。 – Thilo

+0

感謝您指出刪除實際發生在回調中。雖然這是真的,但是如果回調實際上是_synchronous_,那麼刪除將在'forEach'結束之前發生?由於我在調用庫/模塊函數,因此我只能猜測回調是同步還是異步。 – user826955

+0

@ user826955:你根本不應該*猜測*。如果庫有一個接受回調的API,並且它的文檔沒有清楚地告訴你它是否會同步或異步地調用它,那麼這是圖書館文檔中的一個嚴重錯誤,應該這樣報告和處理。 –