Проверьте повторный ввод асинхронной функции в JS - PullRequest
1 голос
/ 26 сентября 2019

Сценарий:

У нас есть 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>

1 Ответ

1 голос
/ 28 сентября 2019

Одним из возможных путей решения этой проблемы может быть остановка наблюдателя мутаций при запуске одной мутации

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','');

function handler(){
    console.log('Modification happend')

        mutationObserver.disconnect();
    //  Trigger a MutationObserver change
    document.getElementById('foo').setAttribute('class','bar');
    document.getElementById('foo').setAttribute('class','');

    mutationObserver.observe(window.document,{
    attributes:true,
    characterData:true,
    childList:true,
    subtree:true
});
}

См. Скрипту JS

https://jsfiddle.net/tarunlalwani/8kf6t2oh/2/

...