What App.reset() does in Ember
An in-depth line by line look at what App.reset() does in Ember
Earlier today I wrote a post show how using App.reset()
helped me with a caching issue, at the end of it I asked if there was maybe something better I can do.
This evening I wanted to take a look at what is actually going on under the hood when you call App.reset();
in your Ember application.
This is going to be a bit of a live blog, where I go through line by line and work out what is happening.
Lets get right down to it, here is the code for reset (as of 1.5.0);
reset: function() {
this._readinessDeferrals = 1;
function handleReset() {
var router = this.__container__.lookup('router:main');
router.reset();
Ember.run(this.__container__, 'destroy');
this.buildContainer();
Ember.run.schedule('actions', this, function() {
this._initialize();
});
}
Ember.run.join(this, handleReset);
},
Fairly short, but there is plenty of stuff going on that I have no idea about, to be honest I was stumped even by the first line;
this._readinessDeferrals = 1;
A quick search revealed this conversation on the Ember.js message boards which talks about a deferReadiness
function which checks for this._readinessDeferrals
being <= 0, so it looks like it is a flag to say that we are not ready just yet. You would call deferReadiness
if you don’t want your app to initialize immediately.
So next we create this handleReset
function, before looking at this in much detail I already know that it performs four main tasks (from my previous post). Knowing this sort of high level thing really helps when you are digging into code, so I will repost it here;
- Deactivate existing routes
- Destroy all objects in the container
- Create a new application container
- Re-route to the existing url
The first thing that happens inside this handleReset
function is that we set up a variable called router
;
var router = this.__container__.lookup('router:main');
I have seen this __container__
variable before, but have never known what it actually corresponds to, a search brings up an old commit that shows that __container__
used to be just container
but people were using it for grabbing controllers without using the proper means. This leads me to believe that __container__
is your main namespaced application.
Calling .lookup
on it and passing in what you want is the main way you interact with __container__
, this is covered in a fair amount of detail in Ember’s debugging guide.
Now we have the main router we call .reset()
;
router.reset();
This makes sense, we are resetting the router, this is a private method detailed here.
Next up it looks like we are destroying the container;
Ember.run(this.__container__, 'destroy');
Ember.run
runs the passed target and method inside of a RunLoop, you can read about it in the Ember docs.
Since we have just destroyed the container, it makes sense that we want to make a new one, this is handled by;
this.buildContainer();
Next up we have the following block of code;
Ember.run.schedule('actions', this, function() {
this._initialize();
});
We see this Ember.run
again and this time we are calling .schedule
on it. We can see that ‘actions’ is the queue we want to add things to, this is the context we want to pass in and then the anonymous function is the thing we actually want to run.
Now we just need to work out what the following actually does;
this._initialize();
This code sits just above our reset code in the Ember codebase; You can see that it goes through and initializes everything that Ember needs to function.
We are down to our final line;
Ember.run.join(this, handleReset);
Something else using the Ember run loop I see! From reading the docs I can see that join will either queue itself to an existing run loop or create a new one. As normal we are passing in a context (or target as Ember calls it) of this
and we are calling handleReset
, our function we just created!
I learned a lot tonight, hope you did too! Let me know if you enjoyed this type of post in the comments, I will do more of them if they are useful.