我正在構建一個undomanager,類似於在各種瀏覽器中尚未準備好的W3C undomanager。我實現了一個簡單的事務處理調用,它在調用DOM時調用回調函數,然後將必要的結構添加到數組中,稍後可用於撤消(或重做)更改。如果在修改DOM後立即調用斷開連接,則不會調用MutationObserver回調
一個簡單的例子:
function transact(callback){
/* Watch content area for mutations */
observer = new MutationObserver(function(){
/* TODO: collect mutations in here */
alert('Mutations observed');
});
observer.observe(document.getElementById('content'), {
attributes: false,
childList: true,
characterData: false,
subtree: false
});
/* Perform the callback */
callback();
/* Stop observing */
//observer.disconnect();
setTimeout(function(){ observer.disconnect();}, 1);
}
要使用此:
transact(function(){
var p = document.createElement('p');
p.innerHTML = 'Hello';
document.getElementById('content').appendChild(p);
});
如果我立即打電話observer.disconnect()
,突變觀察者永遠不會到達alert
電話,但如果我使用的setTimeout,它工作正常。
我會非常樂意接受setTimeout調用,唯一的問題似乎是對於較大的更改,您必須延遲斷開多達800毫秒。
這幾乎就好像斷開發生在DOM更改實際完成之前,因此沒有檢測到任何東西。
這發生在兩個25火狐和Chrome 32
我想了一秒鐘,由於observer
是一個局部變量,也許它超出範圍太快,但將其更改爲一個全局變量沒有幫幫我。我不得不推遲電話disconnect()
給DOM一個看起來似乎趕上的機會。
這是一個瀏覽器的bug嗎?一旦DOM準備好了,有沒有更好的方法可以調用disconnect()
?
通過當前的堆棧,你的意思是調用堆棧? – izak
是的,瀏覽器中的任何*異步*只能在立即調用堆棧爲空之後運行。這裏關於異步函數的線程數量很多 – megawac
@izak抱歉 - 我沒有解決問題 – megawac