Are there any potential memory leaks when using deferreds? - javascript

I get a jQuery.Deferred somewhere in my code, and I add several callbacks to it which are member methods of short-lived objects. I was wondering if there are any kind of memory leak potential in this situation, similarly like in .NET event handlers.
I was checking the code of jQuery, but haven't seen any part where callbacks are cleared. I didn't even find where the lifecycle of a deferred object should end.
Could anyone please shed some light on this topic?
EDIT
As I'm thinking about it, it narrows down to this question. In JavaScript, will holding a reference to a member function of an object (not prototype) deny the object from being GC-d? Because jQuery seems to hold these function references in the callbacks of the deferred object.

I haven't seen any part where callbacks are cleared.
The callbacks are cleared when the promise is settled (fulfilled or rejected).
I didn't even find where the lifecycle of a deferred object should end.
The lifecycle of a promise ends when nothing holds a reference to it any more.
There are generally two things that hold a reference to it: the resolver (e.g. timeout, ajax request etc) that eventually will settle the promise, and entities that store the promise because they want to use it (i.e. its result) later. The promise object in turn holds a reference to all the callbacks (until settled), and to the result value (since settled).
A leak can occur if the promise is never resolved, has callbacks attached to it, and is prevented from being garbage-collected by some references. That's very rare though.
In JavaScript, will holding a reference to a member function of an object (not prototype) deny the object from being GC-d?
No, in general not. There are no "members" in javascript, just plain standalone functions.
Though of course the function, when being a closure, could hold a reference to the object, and would keep it from being collected.

I'll answer my question because it seems to be a simple one after some thinking. Actually JavaScript functions don't belong "tightly" to the objects where they're defined, unless they are manually bound with Function.prototype.bind for example, but that's another case.
So if functions are living their own life, holding a reference to them should not deny collecting the object where it was originally defined.
Also I have to note that this all doesn't even matter if I don't hold a direct or closured reference to the deferred object itself, because then whenever it's done the job (resolved/rejected) it will be collectible.
Please someone more experienced correct me if any assumption is wrong here.

From what I've seen (and some light reading: Do never resolved promises cause memory leak?), there is negligible impact from unresolved Promises -- or Deferrereds -- unless you are:
Creating a large number: hundreds of instances of any object are a drag that requires special handling and design
Maintaining references to instances that prevent a GC run from cleaning up any out-of-scope items

Related

Ensuring object can be garbage collected

My node/javascript program receives lots of messages.
Each time a message is received I create a new object, passing it message content.
Within the new objects constructor, the object does a bunch of stuff, including some mongo operations with callbacks.
When the operations that are performed within the object constructor are complete, the object is no longer needed or wanted.
After some experiments involving complexity (i.e. storage of the object in an array element or as a property of a 'master' object and then deleting it, I tried the simple approach.
var x = new DisposableObject(message);
delete x;
This seems to work fine. There may be many instances of DisposableObject in existence at any time. DisposableObject is created and does everything expected of it in tests.
I am assuming that when I delete 'x' that this does not affect the object itself, just the reference to it that is contained in 'x'. The objects callbacks occur and all is good.
So four questions:
Will this simple mechanism allow the garbage collector (node/V8) to get rid of the object?
Is there some awful trap door awaiting my code because I am doing this?
Is there any issue with multiple instances of DisposableObject floating around waiting for callbacks when there is no active reference left to them in my program?
Is there a better way to create the objects, then make sure they can be garbage collected after all their operations are completed?
Javascript uses a nongenerational mark-and-sweep garbage collector, in javascript objects are automatically garbage collected when they are no longer needed , so you need not worry about garbage collection.
but you have to keep these points in mind (from this answer):
what you are trying with delete does not really delete an object, delete is only effective on an object's properties. It has no effect on variable or function names., Use delete statements whenever you create an object using a new statement, pair it with a delete statement. This ensures that all of the memory associated with the object, including its property name, is available for garbage collection. The delete statement is discussed more in “Freeing Objects.”
Use the var keyword. Any variable created without the var keyword is created at the global scope and is never eligible for garbage collection, presenting the opportunity for a memory leak.
In case of global variables, Global variables are never disposed of by the GC in the sense that a global variable will always exist. Setting it to null will allow the memory that it references to be collected. the memory used by the object will be eligible for collection. but The variable still exists though, and it simply references null(some more here)

Should a JS API Convert jqXHRs to Promises?

I've seen a pattern of people converting their jqXHR objects (ie. those things JQuery returns when you do an AJAX operation) in to promises. For instance:
function doAJAX() {
var jqXHR = $.get('http://www.example.com');
return jqXHR.promise();
}
I've never bothered with this pattern because it doesn't seem to really offer anything. When people talk about converting $.Deffereds to $.Promises they recommend doing so to prevent the user from prematurely resolving the deferred. But jqXHRs already effectively are promises: they implement the promise interface and they can't be resolved prematurely.
But, I'm now working on a public-facing API, where I'm willing to bend over backwards (code-wise) if it will result in a better API for the customer. So, my question is, am I missing anything? Will throwing .promise() after every AJAX call that gets returned to the customer actually make things better for them in any way, or is this just an example of patternitis where people apply .promise() to their jqXHRs simply because they're used to doing it to their deferreds?
jQuery's jqXHR as returned from $.get() is already a fully functioning promise object, not a deferred object so it is already protected as a promise. You don't need to convert it into one and doing so only hides existing jqXHR functionality.
So, you can already directly do this:
$.get('http://www.example.com').done(function() {
// your code here
});
Straight from the jQuery doc for $.get();
As of jQuery 1.5, all of jQuery's Ajax methods return a superset of
the XMLHTTPRequest object. This jQuery XHR object, or "jqXHR,"
returned by $.get() implements the Promise interface, giving it all
the properties, methods, and behavior of a Promise (see Deferred
object for more information). ...
The Promise interface also allows jQuery's Ajax methods, including
$.get(), to chain multiple .done(), .fail(), and .always() callbacks
on a single request, and even to assign these callbacks after the
request may have completed. If the request is already complete, the
callback is fired immediately.
And, to your question:
Will throwing .promise() after every AJAX call that gets returned to
the customer actually make things better for them in any way?
No, in my opinion, this will not help make it a better API as it will only serve to hide the jqXHR functionality and turn it into only a promise. The jQXHR object is already a promise object and not a deferred object so the promise aspect of protection against people mucking with the deferred is already there.
The only reason I can think of to return ONLY a promise object from your API would be if you're truly trying to hide the fact that you're using jQuery underneath so you don't want there to be any way for the API user to use any other jQuery features. But, unless you're also hiding ALL the argument functionality on the input to the Ajax call (so it can't look like jQuery on the input side of things either), then I see no point in hiding output functionality either. After all, it is jQuery underneath so why go to all the trouble of abstracting/redefining the whole jQuery ajax interface.
Most best practices are invented not to get things done now, but to get things done further down the road as well. It all
revolves around maintainability, reusability, flexibility etc. Requirements and technology change and your code should be robust enough to be able to adapt to those changes. The more tight coupling between components for instance, the harder it is to change a part without affecting other parts.
When designing a public facing API this is really important as well, probably even more so, since you should try not only making things easy for your future self, but also for all the users of your API. Backwards compatibility is one of these things users of an API really like, since it means they can upgrade your library w/o breaking any existing code. Obviously it's not always possible to make everything 100% backwards compatible (or sometimes it's not even desirable) It's a balancing act. Try to foresee possible future changes and code towards them. However this doesn't mean you should try jumping through hoops just because maybe one day this or that will change. You need to weigh the pros and cons and analyse the amount of work involved.
Now let's get to the question:
If you return a jqXHR object from your method people will start using it not just as a promise, but as a full-fledged jqXHR object. They'll see it for what it is in the documentation, source code or their inspector and they _will_start using it as that. This means that their code expects not just a promise, but a jqXHR object, since that's what they are using. However this limits you the creator of the public API, because if one day down the road for whatever reason you don't want to return a jqXHR object you'll be making changes that aren't backwards compatible.
So let's assess how realistic this scenario is and what the solution is.
Possible reasons why you might not be returning a jqXHR object in the future include (but are not limited to):
What if you decide to use a different library instead of Jquery (for this method)?
What if you need/want a different retrieval mechanism? For instance instead of retrieving data through ajax, you want to retrieve it from LocalStorage. Or maybe both?
What if you want to wrap jquery promises with a promise library (for instance Q allows you to do this, since jquery promises aren't proper promises)?
What if the flow changes and this method is only the first in a sequence of distributed processors?
In all of the above cases you will either jump through hoops (like for instance passing a stale jqXHR object around) to avoid breaking backward compatibility or you'll just break it. In all of the above cases people that have been using the returned object not only as a promise, but as a jqXHR object will have to change their code. This can be quite a substantial change.
Now let's get back to the balancing thing. None of the above scenario's are a concern if the solution to avoid some of the potential headaches would be convoluted or elaborate, but it's not. It's just one simple thing:
return jqXHR.promise();
The implementation detail is abstracted away, people don't know and especially can't rely on one specific implementation detail. I can almost guarantee you that it will save you trouble.
Many people seem to have a kneejerk reaction when it comes to best practices: "but it's totally possible to do it with [other solution]". Sure. Nobody's saying it's impossible or insurmountable. You just try to keep things easy both now and in the future.

What happens to a jQuery promise after it is done being used?

It seems that there is no way for jQuery to know when your app is done using a promise. Since memory is managed in js, I presume that the promise continues to exist until all references to it are gone. Specifically, it will exist indefinitely until it is resolved AND the code that created or used it has finished exiting (functions returned etc). At which point it will be garbaged collected.
Can anyone verify my assumptions? Or add other thoughts to this?
Understanding the underlying mechanics has some important connotations; memory leaks, potential caching opportunities (via persisting promises after they have been resolved), etc. My next step is to dive into the jQuery source, but I was hoping for some additional guidance before starting that.
If there are no references to a resolved promise, it will (eventually) be disposed. Otherwise, it will be kept in memory in case anyone wants to access its value.
Promises are no different here from any other object in this case.
Promises are only removed in one case, if the progress is done.
js source
.done( updateFunc( i, resolveContexts, resolveValues ) )
...->
deferred.resolveWith( contexts, values );
To note, resolveWith is part of jQuery convention to use what they call a tuple, resolve in this case, suffixed with "With" in order to essentially issue a callback to deferred.resolve. This essentially calls the original callback using the same context as the deferred object.
Internally when a callback from a list is fired, jQuery will remove that from the list of callbacks held for that list.
Thus, the only way a promise is resolved, is by being done. There is no timing which monitors it.
The promise will either be attached to the target if one is passed in the jQuery constructor, or will be attached to a new instance of jQuery. This will be the lifetime of the list which holds these deferred callback lists.
As with any other garbage collection, this lifetime will be browser dependent (IE sometimes does interesting things).

Is promise a closure?

In closure tag wiki page, it reads "jQuery itself is one big closure."
But is promise a closure as well? Could you please explain why or why not? This is how I understand closure: assign a function to a variable and reuse it with different environments. Promise does that with $.ajax(), but I could not find anywhere in stackoverflow where promise is introduced as a closure. Maybe because there are other features of promise like $.Deferred(), resolve(), and fail() to expand its functionality beyond a simple function passing?
Closures
This is how I understand closure: assign a function to a variable and reuse it with different environments.
That's not a strictly accurate definition of a closure.
A closure is a function that has access to a referencing-environment. In Javascript, that means a function that is returned by another function and has access to the original functions scope. there are other SO questions that describe this very well
Closure's are general purpose structures that can be used in a variety of ways. One of their biggest benefits is that they protect private scope, which is why libraries like jQuery are often written as closures, so that they don't need to expose all their functions globally.
Promises
Promises are a different concept. They are a way of structuring asynchronous code to make it easier to follow the flow. A promise object in particular is an object that provides functions to chain operations in a clear and easy to read way. A promise might be implemented using closures, but it does not have to be. For instance here is an implementation that does not use closures:
https://gist.github.com/814052/690a6b41dc8445479676b347f1ed49f4fd0b1637
whereas jQuery's implementation uses at least one closure, but isn't really based on them
http://james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.Deferred
Conclusion
Promises and Closures aren't directly related concepts. Closure's are a programming technique that might be used in a Promise implementation. In the end it is neither impossible or necessary to implement it like that.
You wouldn't ask if a birdhouse was a 2x4, even if you used one to make it. The same can be said of promises and closures. Promises make use of closures to retain references to state, callbacks and other such things.
Because of the nature of JavaScript, being asynchronous that is, we are provide much power by the language and it's runtimes. First off, a Promise in jQuery, although it is not unique to jQuery, is an object that will as the documentation puts it, observe when all actions of a certain type bound to the collection, queued or not, have finished. This means you can use this object to know when to continue after a set or queue of items has finished some behavior. Now a Closure on the other hand is not unique to jQuery, but is rather a JavaScript construct, one that combines two things: a function, and the environment in which that function was created. This means that not only executing a function but doing so in possibly an entirely different context.
Closures and Promise are different concepts. Closures refers to scope of variables where as promise are used to 'promise' that an act on something will occur when it is done on an asynchronous action. Since Javascript is non-blocking (not asynchronous --edit), it will not wait for a function to get a response if it needs to access the internet or disk, that said you can have a promise execute after something is done.

Best practise for context mode at runtime in JS

I have a web application based on apache. php, js and jquery. All works fine.
On the client side there is a small library in JS/jquery, offering some generic list handling methods. In the past I used callbacks to handle those few issues where those methods had to behave slightly different. That way I can reuse methods like list handling, dialog handling and stuff for different part of the application. However recently the number of callbacks I had to hand through when stepping into the library grew and I am trying a redesign:
Instead of specifying all callbacks as function arguments I created a central catalog object in the library. Each module of the application registers its own variant of callbacks into that catalog upon initialization. At runtime the methods lookup the required callbacks in that catalog instead of expecting it specified in their list of arguments. This cleans up things quite a lot.
However I have one thing I still cannot get rid of: I require a single argument (I call it context, mode might be another term) that is used by the methods to lookup the required callback in the catalog. This context has to be handed through to all methods. Certainly better than all sorts of different callbacks being specified everywhere, but I wonder if I can get rid of that last one to.
But where do I specify that context, if not as method argument ? I am pretty new to JS and jquery, so I failed to find an approach for this. Apparently I don't want to use global vars, and to be frank I doubt that I can simply store a context in a single variable anyway, since because of all the event handlers and external influences methods might be called in different contexts at the same time, or at least interleaving. So I guess I need something closer to a function stack. Maybe I can simply push a context object to the stack and read that from within the layers of the library that need to know ? The object would be removed when I leave the library again. Certainly other approaches exist too.
Here are so many experienced coders how certainly can give a newbie like a short hint, a starting point that leads to an idea, how to implement this. How is such thing 'usually' done ?
I tried round a while, exploring the arguments.callee.caller hierarchy. I thought maybe I could set a prototype member inside a calling function, then, when execution steps further down I could simply traverse the call stack upwards until I find a caller holding such property and use that value as context.
However I also saw the ongoing discussions that reveal two things: 1.) arguments.callee appears to be depreciated and 2.) it appears to be really expensive. So that is a no go.
I also read about the Function.caller alternative (which appears not to be depreciated and much more efficient, however until now I failed to explore that trail...
As written currently passing the context/mode down simply works by specifying an additional argument in the function calls. It carries a unique string that is used as a key when consulting the catalog. So something like this (not copied, but written as primitive example):
<!-- callbacks -->
callback_inner_task_base:function(arg1,arg2){
// do something with args
}
callback_inner_task_spec:function(arg1,arg2){
// do something with args
}
<!-- catalog -->
Catalog.Callback:function(context,slot){
// some plausibility checks...
return Catalog[context][slot];
}
Catalog.base.slot=callback_inner_task_base;
Catalog.spec.slot=callback_inner_task_spec;
<!-- callee -->
do_something:function(arg1,arg2,context){
...
// callback as taken from the catalog
Catalog.Callback(callback,'inner_task')(arg1,arg2);
...
}
<!-- caller -->
init:function(...){
...
do_something('thing-1',thing-2','base');
do_something('thing-1',thing-2','spec');
...
}
But where do I specify that context, if not as method argument ?
Use a function property, such as Catalog.Callback.context
Use a monad

Categories

Resources