Skip to content
This repository has been archived by the owner on Mar 22, 2019. It is now read-only.

Commit

Permalink
Merge pull request #1951 from emberjs/app-instances
Browse files Browse the repository at this point in the history
Instance initializers deprecation
  • Loading branch information
wycats committed Aug 11, 2015
2 parents c598161 + e33c152 commit 4e0562e
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
3 changes: 3 additions & 0 deletions source/deprecations/v1.x.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ App.instanceInitializer({

Added in [PR #10256](https://github.com/emberjs/ember.js/pull/10256).

For more information, see [the instance initializer deprecation
guide](deprecations/1.11/instance-initializers).

### Warnings Added in 1.11

#### Binding Style Attributes
Expand Down
118 changes: 118 additions & 0 deletions source/guides/deprecations/1.11/instance-initializers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
## Deprecate Access to Instance Initializers

When we initially designed Ember, we only had the use case of apps that
run in the browser in mind. In that world, you would load your app and
then it would run until the user closed the tab or navigated away.

For testing, we quickly realized that we would need some way to "reset"
the application between each test without reloading the page and
starting from scratch. To that end, we isolated all of the state in an
application into an object called the container that could be thrown
away after each test had completed.

We wanted a shared way for both apps and add-ons to initialize
applications when they booted and loaded. In particular, it was
important for people to get access to that container to make objects
available to the app at runtime. To do so, we introduced the initializer
API.

For example, Ember Data uses this API to ensure that all of your
controllers and routes have access to the store object.

As we have been working on the FastBoot effort to allow Ember apps to
run on the server, we realized that the assumption that there would only
be one instance of the app running at once no longer held.

In particular, we realized that "app boot" was actually two distinct
phases:

1. Loading all of your application code and registering objects with the
application (such as the store in the Ember Data example)
2. Instantiating objects when the app starts running

When the application boots up for the first time, we need to run Step 1
above, but it would be wasteful to run it for every request going to
your FastBoot server.

We also realized that a huge number of real-world initializers were
simply registering classes and injections, while a smaller fraction of
initializers are doing work that truly needs to be done per run.

By separating out these two kinds of work, we could improve the
performance of cases where a single application was used multiple times,
each with a fresh set of state.

This applies to FastBoot, of course, but it also applies to integration
tests. Today, integration tests spend time executing code in
initializers that don't change between test runs, simply because of the
possibility that the initializer may also set up instances.

Thankfully, the `initializer` infrastructure already clearly marks the
boot-up phase of your application (both in your own code and in
add-ons), so we only need to make a small tweak to `initializer`s for
FastBoot to work.

This change makes the difference between initializers that set up code
and initializers that set up instances explicit.

The old `App.initializer` API now receives a `registry`, which can be
freely used to set up code using the `register` API and the various
`inject` APIs.

A new `App.instanceInitializer` API receives an `ApplicationInstance`
object. When migrating code, the most important property on the
`ApplicationInstance` is `container`, which you can use to get new
instances and set state on them.

Migrating code to the new structure is fairly mechanical. Change code
that looks like:

```js
App.initializer({
name: "clock",

initialize: function(container) {
container.register("clock:main", Clock);
var clock = container.lookup("clock:main");
clock.setStartTime(Date.now());
}
});
```

To:

```js
App.initializer({
name: "clock",

initialize: function(registry) {
registry.register("clock:main", Clock);
}
});

App.instanceInitializer({
name: "clock",

initialize: function(instance) {
var clock = instance.container.lookup("clock:main");
clock.setStartTime(Date.now());
}
});
```

Some things to remember:

1. All `instanceInitializer`s run after `initializer`s and do not share a
namespace. You can use the same name in both, and don't have to use
`before` or `after` to make sure that instance initializers run
second.
2. The deprecated `registry.lookup` works by maintaining a 1:1 mapping
between Application and a default `ApplicationInstance`. This is
fundamentally incompatible with FastBoot, and you will need to clear
this deprecation warning before you will be able to use any of the
FastBoot features.

While FastBoot and the improved testing performance have not yet landed,
these changes allow us to continue work on those APIs after Ember 2.0.
It also future-proofs Ember for more situations where a single
`Application` has multiple runs over its lifetime.

0 comments on commit 4e0562e

Please sign in to comment.