Recently I am working on single page application, which leads to have deep dive into browser's memory model and JS garbage collector. I am also looking at different tools to do memory profiling and heapdump on different browsers.
There are two kinds of garbage collection algorithms: reference counting and mark-and-sweep. As we know finding out unreachable objects is undecidable in computer science. Those two algorithms are not always perfect.
Reference counting is essentially by keeping tracking of number of references to the objects once the count reaches 0 then gc will be triggered. However there is well-knows issue with that: it doesn't clean up the two objects have references to each other but on other references to these two objects. It is called "cycle reference."
Modern JS engines use mark-and-sweep garbage collection, basically it goes down from root Object to "unmark" the each object which can be reached. Then marked objects are considered as gc'd.
However this gc model is not compitale with browser's component object model DOM object handling. For example, IE's Windows COM use reference counting so does FreFox's XPCOM.
There certain memory leak patterns which are well documented:
1. circular reference between DOM and JS objects, DOM<->JS, please note this only apply to IE browser versions older than IE8.
As stated before, JS garbage collector can identify the cycle reference by going down the object hierarchy but not for the cycle reference between DOM object and JS object. And since DOM and JS have different garbage collection algorithm, so the above creates memory leak.
- Solution: set dom element reference in JS to null on unload() event.
2. closure: functions nested inside function, gain access to the outer function's variables it is known as closure.
function(){
var obj = domElement;
domElement.onclick = function(){ // this create new object which reference to domElement and domElement has onclick property reference back to this function obj, cycle reference
}
// obj = null; //solution is to set obj to null when function returns
}
3. inline script, the internal scripting object. If you create dom element with inline script thousands of times the memory leak will happen.
4. DOM object insertion order.
Each insertion of dom element will inherit the scope of the parent object which effectively create new object. If Dom element creation and insert happens alone from the document object, then temporary object will be created and leak.
The solution is to append child to document object first.
User case:
User
login mobile application, and on behave of user mobile application
sends every Ajax request to back-end service along with an authorization
token, server will give 401 status if "session" or token is expired
time out.
Solution:
a.
Use global .Ajaxsetting() to specify the status code 401 call back
function. It is probably the easiest way. However in this approach the
ajax call error will still bubble up event chain and will still trigger
the subsequently error handler. So it only works if you redirect user to
login page immediately.
b. Use promise chain error call back to trap the error.
Let's look at promise.then(success, error) function. It returns a promise itself.
The
promise is resolved if 1) success/error return a value or 2) the
returned value is a promise, then it is resolved with this promise.
The promise is rejected if success / error throws an error.
So
if we simply return a dummy value when 401 is caught, then it will be
passed to the next successHandler. then in the successHandler we need to
differentiate the trapped error and real success response.



