Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of $.cache in jQuery?

I see that the event handlers registered through .on() are held in $.cache. I also see that the event handlers are also held in $(elem).data().

The objects held in $.cache refer to the DOM nodes on which the events are registered. This leads to memory leak when the DOM nodes are detached, and this makes .off() calls mandatory.

I have a situation where I don't know when the DOM node (to which I attached the event handler) is being detached. While I can hold the reference to that DOM node in my code and call .off() to clean up, it doesn't seem nice, because it is not straightforward to know when the DOM node is being removed.

What is the best way to do this?

like image 605
user968903 Avatar asked Feb 16 '12 02:02

user968903


People also ask

Why use cache false in ajax?

The cache: false is used by developers to prevent all future AJAX requests from being cached, regardless of which jQuery method they use. We can use $. ajaxSetup({cache:false}); to apply the technique for all AJAX functions.

What is cache true in Ajax?

cache:true is the default and does not always get the content from the cache. The cache-ability of an item on the browser is determined by: The response headers returned from the origin web server. If the headers indicate that content should not be cached then it won't be.

Do ajax requests get cached?

Although we can use a standard caching solution provided by HTTP (yes, Ajax is cached by HTTP), there is a catch: It works for GET requests only (not POST).

Whats is cache?

In computing, a cache is a high-speed data storage layer which stores a subset of data, typically transient in nature, so that future requests for that data are served up faster than is possible by accessing the data's primary storage location.


2 Answers

"What is the best way to do this?"

If you're going to use jQuery, you must use its API for removing elements, and you must use the proper methods, otherwise, as you stated, you'll have memory leaks.

If you don't know when the DOM node is being removed, and if it is causing a leak, I'd assume this means that you are using another library alongside jQuery. That's just not a good idea for this very reason.

You need to ensure that any elements affected by jQuery are removed by jQuery. There's also some data stored in $.cache that you didn't explicitly set. This means that all elements should be removed with jQuery, instead of just those that you think may have data.


"What is the purpose of $.cache in jQuery?"

To associate handlers and other data with elements. The link between the data and the elements is basically a serial number stored on an expando property on the element.

If you remove the element without jQuery, the associated data in $.cache is orphaned.

The purpose of this approach was to prevent potential leaks. Unfortunately it potentially creates more severe leaks.

like image 138
2 revsuser1106925 Avatar answered Sep 20 '22 16:09

2 revsuser1106925


I ran in to a similar situation where Knockout is used to add and remove dom trees from the document. However, jquery is used to attach event listeners to these dom trees. When knockout removes dom elements from the document the listeners are not unbound so the dom tree is never eligible for garbage collection. We have added a clean up function that trawls through the jquery $.cache everytime the hash changes and finds even handlers that are bound to dom trees that are not in the document. It then unbinds the listeners thus making the dom tree eligible for garbage collection and fixing most of the leaks that we are seeing i.e. round trip round the app used to leak 13MB now it leaks just 3MB with these changes in place.

for (var i in $.cache) {
            if ($.cache.hasOwnProperty(i)) {

                if ($.cache[i].handle && $.cache[i].handle.elem && document !== $.cache[i].handle.elem && !jQuery.contains(document, $.cache[i].handle.elem)) {
                    //we have an event handler pointing to a detached dom element!
                    //this is a memory leak as this detached dom element cannot be garbage collected until
                    //all references to it are removed. So lets delete the event handler to get memory back!
                    var orphan = $($.cache[i].handle.elem);
                    $('body').append(orphan);
                    orphan.off();
                    orphan.remove();
                    orphan = null;
                }
            }
        }
like image 30
Troup Avatar answered Sep 24 '22 16:09

Troup