The Ember run
loop is an extremely important part of Ember's internals. The run
loop is used to batch, order, and work in a way that's most efficient for the Ember application. In this recipe, we'll create a simple timer and take a look at how the run
loop works.
Before we move on to our recipe, we'll need to understand some basics of the Ember run
loop.
The Ember
run
loop consists of six queues as follows:
sync
: This queue consists of binding synchronization jobs.actions
: This queue contains general work and promises.routerTransitions
: This queue contains transition jobs in the router.render
: This queue contains jobs meant to render, usually to update the DOM.afterRender
: This queue is run after all previously scheduled render tasks are completed. This queue is typically used for third-party applications.destroy
: This last queue tears down objects.These queues don't run all the time. They only run in response to certain user and timer events. This way, responsibility is handed back to the user; otherwise, the browser would hang.
You should make changes to the Ember run
loop only in certain situations:
PostMessage
and messageChannel
event handlersMost of the time, Ember's run
loop will handle everything and you won't need to touch it.
The Ember run namespace gives us several methods to use when working with the run
loop. The most popular methods are as follows:
Ember.run.bind
: This is great for use in third-party libraries, and adds the execution of the function to Ember's run
loopEmber.run.later
: This runs the passed target/method after a specified period of timeEmber.run.schedule
: This runs the passed target/method and optional arguments to the named queue at the end of the loopThere are more methods available, but these are the ones you'll use the most when you need to manipulate the run
loop.
time-checker
component:$ ember g component time-checker $ bower install moment –save
This will generate a new component called time-checker
. In addition, we'll be using the Moment library to keep track of our timer.
// ember-cli-build.js /*jshint node:true*/ /* global require, module */ var EmberApp = require('ember-cli/lib/broccoli/ember-app'); module.exports = function(defaults) { var app = new EmberApp(defaults, { // Add options here }); app.import('bower_components/moment/min/moment.min.js'); return app.toTree(); };
This adds the Moment library to the application.
time-checker.js
component file. Add two properties to it—one to show the time when the component started and another to show the current time:// app/components/time-checker.js /* global moment */ import Ember from 'ember'; export default Ember.Component.extend({ startTime: null, currentTime:null, init(){ this._super(...arguments); this.set('startTime',moment()); this.startWatchingTime(); }, startWatchingTime(){ this.set('currentTime', moment()); Ember.run.later(()=>{ this.startWatchingTime(); }, 1000); }, diff: Ember.computed('startTime','currentTime', function(){ return this.get('currentTime').diff(this.get('startTime'),'seconds'); }) });
The purpose of this component is to display the time when the component loaded and the current time. It also shows the difference between these two times. Let's take a look at this in more detail:
init(){ this._super(...arguments); this.set('startTime',moment()); this.startWatchingTime(); }, startWatchingTime(){ this.set('currentTime', moment()); Ember.run.later(()=>{ this.startWatchingTime(); }, 1000);
The init
function runs as soon as the component is instantiated. It sets the current time and calls the startWatchingTime
method. This method uses Ember.run.later
to wait a second before continuing. Each second, it calls itself, and then calculates the new date and time again. It's better to use this method than setTimeout
, as it may cause issues in the Ember run
loop:
diff: Ember.computed('startTime','currentTime', function(){ return this.get('currentTime').diff(this.get('startTime'),'seconds'); })
The diff
computed property updates whenever currentTime
changes. It returns the difference in seconds between the two times.
time-checker.hbs
component file:// app/templates/components/time-checker.hbs Startup time: {{startTime}}<br> Current time: {{currentTime}}<br> Difference: {{diff}}
This will display the start, current, and difference times.
<h2 id="title">Welcome to Ember</h2> {{time-checker}}
This will add the time-checker
component to the application.
The Ember run
loop makes this possible.
The Ember run
loop helps schedule work in an Ember application. It runs whenever there is user action or certain timing events. It consists of six different queues. Each queue is responsible for different functions in the application.
In most situations, you don't need to worry about the run
loop. However, in some situations such as dealing with asynchronous callbacks or timing events, you'll need to use them. Keep this in mind as you continue to program in the future.