2

We are currently successfully detecting mutations of target DOM elements within our page. We are now looking at aggregating certain properties of these target node mutations in a 'list' to send via an AJAX call for processing on the server. The callback from the server will allow us to modify attributes on these target elements en masse.

However, the problem is WHEN to make the first Ajax call. Obviously we know when the mutations start (thus adding to the list). However, we never know when they end (MutationObserver is idle) to then make our AJAX call. We could, of course, write a function that checks the size of the list, along with a period of time passed, to make our Ajax call that contains the contents of our aggregated list when the function wakes up.

Is this it or is there a better way of handling this?

Thoughts appreciated!

MoMo
  • 1,836
  • 1
  • 21
  • 38

2 Answers2

7

You can use a debounce function so that the function is only called after for a period of time p

Underscore js offers a nice debounce function which you can use as below:

var observer = new MutationObserver(_.debounce(function() {
    //make ajax calls and stuff
}, 1000));//the ajax function wont be called until 1000 ms have passed

observer.observe(document, {childList:true});

So this will prevent your ajax call from being made until 1 second has elapsed since the last mutation and it will not fire if there was not a 1 sec since the previous mutation.

Here's perhaps the simplest implementation from an old version of underscore and a perf test comparing different implementations

megawac
  • 10,953
  • 5
  • 40
  • 61
  • Thank you for the response. It seems, your suggestion is a varied implementation of the notion we had envisioned. In other words, there is no way to detect 'true' idle unless it is done over a pre-defined span of time. Thanks again and Happy Holidays! – MoMo Dec 28 '13 at 02:00
2

I do something like this:

let updatesOccur = true;
const observer = new MutationObserver((mutations) => {
  updatesOccur = true;
});
observer.observe(window.document, {attributes: true, childList: true, characterData: true, subtree: true});
let mutationsCompletedCallback = () =>
{
  if (updatesOccur) {
    updatesOccur = false;
    setTimeout(mutationsCompletedCallback, 250);
  } else {
    observer.takeRecords();
    observer.disconnect();
    console.log('NO MORE MUTATIONS!');
  }
};
mutationsCompletedCallback();
AGPX
  • 364
  • 3
  • 10
  • why are you putting `mutations` in tho the MutationsObesver callback function? this loop just always runs once lol – AGrush Jul 29 '20 at 10:04