Сценарий:
У нас есть MutationObserver
функция обработчика handler
.
В handler
мы выполняем некоторые манипуляции с DOM, которые снова вызывают handler
.Концептуально, у нас будет реентерабельный handler
звонок.За исключением того, что MutationObserver
не запускается в потоке, он будет запускаться после того, как handler
уже завершил выполнение.
Итак, handler
будет запускаться сам, но через асинхронную очередь, а не в потоке,Похоже, что отладчик JS знает об этом, он будет сам в качестве асинхронного предка в стеке вызовов (т. Е. С использованием Chrome).
Чтобы реализовать эффективный отладку событий, нам необходимо обнаружить это;то есть, если handler
был вызван в результате изменений, вызванных самим собой.
Так как это сделать?
mutationObserver=new MutationObserver(handler);
mutationObserver.observe(window.document,{
attributes:true,
characterData:true,
childList:true,
subtree:true
});
// Trigger a MutationObserver change
document.getElementById('foo').setAttribute('class','bar');
document.getElementById('foo').setAttribute('class','');
var isHandling;
function handler(){
console.log('handler');
// The test below won't work, as the re-entrant call
// is placed out-of-sync, after isHandling has been reset
if(isHandling){
console.log('Re-entry!');
// Throttle/debounce and completely different handling logic
return;
}
isHandling=true;
// Trigger a MutationObserver change
document.getElementById('foo').setAttribute('class','bar');
document.getElementById('foo').setAttribute('class','');
isHandling=false;
}
<div id="foo"></div>