setTimeout keeps executing the same function many

2019-08-25 01:55发布

问题:

I have this code:

document.addEventListener("DOMContentLoaded", function(event) {
  // Select the node that will be observed for mutations
  var parentOfMyList = document.body;

  // Options for the observer (which mutations to observe)
  var config = {
    attributes: true,
    childList: true,
    subtree: true
  };

  // Callback function to execute when mutations are observed
  var callback = function(mutationsList) {
    for (var mutation of mutationsList) {
      if (mutation.type == 'childList') {

        if (document.getElementById("topcmm-123flashchat-main-toolbar-message-type-option") != null) {
          var elt = document.getElementById("topcmm-123flashchat-main-toolbar-message-type-option");
          setTimeout(elt.click.bind(elt), 2000);
          if (document.getElementById("topcmm-123flashchat-toolbar-style-send-sound-btn") != null) {
            var clic2 = document.getElementById("topcmm-123flashchat-toolbar-style-send-sound-btn");
            setTimeout(clic2.click.bind(clic2), 2100);
            if (document.getElementById("topcmm-123flashchat-send-message-panel-close-icon") != null) {
              var clic3 = document.getElementById("topcmm-123flashchat-send-message-panel-close-icon");
              setTimeout(clic3.click.bind(clic3), 2200);

              //execute some function
            }
          }
        }
      }
    }
  };

  // Create an observer instance linked to the callback function
  var observer = new MutationObserver(callback);
  observer.observe(parentOfMyList, config);
});

the code is supposed to execute some function (not included here for the sake of convenience) which cant be executed until topcmm-123flashchat-sound-messages-contents is present in DOM which wont appear until topcmm-123flashchat-toolbar-style-send-sound-btn appears and is clicked, and this one wont appear in DOM either until topcmm-123flashchat-main-toolbar-message-type-option appears and is clicked as well.

So I wrote the code above in order to automatically click on the elements one after another and have them appear in the DOM so the function in questions can be executed.

topcmm-123flashchat-main-toolbar-message-type-option will appear by itself about 3 seconds later after the page loads, if clicked then topcmm-123flashchat-toolbar-style-send-sound-btn will appear and if that one is clicked then topcmm-123flashchat-sound-messages-contents will appear and the function will be executed. I additionally have topcmm-123flashchat-send-message-panel-close-icon clicked in order to have the panels that opened with the previous clicks closed.

The problem here is the panels keep opening like if elt and click2 are executed many times whereas click3 doesnt seem to be executed. Why is that?

Thank you.

回答1:

You need to add logic to prevent repeating the same action for an element that was added previously.

I've added a variable that holds the element. The first time the element is seen, the variable empty, so the if code runs. It's skipped on future runs.

document.addEventListener("DOMContentLoaded", function(event) {
  // Select the node that will be observed for mutations
  var parentOfMyList = document.body;

  // Options for the observer (which mutations to observe)
  var config = {
    attributes: true,
    childList: true,
    subtree: true
  };

  var elt = null,
    clic2 = null,
    clic3 = null;
  // Callback function to execute when mutations are observed
  var callback = function(mutationsList) {
    for (var mutation of mutationsList) {
      if (mutation.type == 'childList') {
        if (!elt && (elt = document.getElementById("topcmm-123flashchat-main-toolbar-message-type-option"))) {
          setTimeout(elt.click.bind(elt), 2000);
        }
        if (!clic2 && (clic2 = document.getElementById("topcmm-123flashchat-toolbar-style-send-sound-btn"))) {
          setTimeout(clic2.click.bind(clic2), 2100);
        }
        if (!clic3 && (clic3 = document.getElementById("topcmm-123flashchat-send-message-panel-close-icon"))) {
          setTimeout(clic3.click.bind(clic3), 2200);
        }
      }
      break;
    }
  };

  // Create an observer instance linked to the callback function
  var observer = new MutationObserver(callback);
  observer.observe(parentOfMyList, config);

  // other code can go here
});