Avoiding memory leaks winjs EventListeners

2019-03-31 22:51发布

问题:

I want to know if I add an event listener to a button, do I have to remove it on unload? Would pressing the 'back' button automatic removes everything current page elements in which I don't need to worry about memory leaks?

(function () {
"use strict";
ui.Pages.define("/pages/registraton/registraton.html",{
    ready: function (element, options) {
        document.getElementById("submitRegister").addEventListener(
            "click", postRegistration , false);

    },
    unload: function () {
        document.getElementById("submitRegister").removeEventListener(
       "click", postRegistration, false);
    }
});...

Thanks in advance.

回答1:

You need to worry about memory leaks in the single-page navigation model that the WinJS.Navigation namespace promotes.

The model you've set up -- where by you implement unload -- is definitely the right approach. How complex & deep you want to get depends on the complexity of your application. Specifically, if you have multiple controls, with multiple manual event handlers you may want to create a set of helpers to enable you to clean up those handlers in one swoop. This may be as simple as pushing element, event name, and the handler instance into an array when when leaving that page and destroying/removing it from the DOM, you can just burn through the array removing the items that need to be cleaned up.

Note that you need to only need to explicitly clean up the case where the handler, and the DOM object have different life times. If they go away together -- e.g. a control attached to a DOM element in the page then you don't have to clean up the everything explicitly. The Garbage Collector will eventually clean it up. If you are a particularly memory heavy application, you may get some wins here by removing the listeners more aggressively.

There are some other things to remember:

  • This also applies to pure javascript objects that implement the addEventListener contract i.e. the list view
  • Don't use attachEvent -- it's going to cause unbreakable cycles due to it's old implementation under the covers. It is actually a deprecated API, so shouldn't be used anyway
  • Be wary when you supply event handlers where you've bound the this pointer, when your trying to unbind them. E.g.

Example:

var element = getInterestingElement();
element.addEventListener("click", this.handleClick.bind(this));

If you try to detach the event, you're lost -- the return valud from the .bind() is lost in the wind, and you'll never be able to unhook it:

var element = getInterestingElement();
element.removeEventListener("click", this.handleClick); // Won't remove the listener
element.removeEventListener("click", this.handleClick.bind(this)); // Won't remove, since it's a different function object

The best solution here is to either monkey patch handleClick before attaching it: this.handleClick = this.handleClick.bind(this);

Or store it away for later use:

this.handlerClickToCleanup = this.handleClick.bind(this);
element.addEventListener("click", this.handleClickToCleanup);