Learning the Ember run loop

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.

Getting ready

Before we move on to our recipe, we'll need to understand some basics of the Ember run loop.

Understanding Ember run queues

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.

When should you change the Ember run loop?

You should make changes to the Ember run loop only in certain situations:

  • Asynchronous callbacks
  • Dealing with timers
  • Ajax callbacks
  • Certain types of tests
  • WebSockets
  • PostMessage and messageChannel event handlers

Most of the time, Ember's run loop will handle everything and you won't need to touch it.

Working with the Ember.run namespace

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 loop
  • Ember.run.later: This runs the passed target/method after a specified period of time
  • Ember.run.schedule: This runs the passed target/method and optional arguments to the named queue at the end of the loop

There are more methods available, but these are the ones you'll use the most when you need to manipulate the run loop.

How to do it...

  1. In a new application, generate a new 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.

  2. Import the Moment library to the application:
    // 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.

  3. Update the new 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.

  4. Update the template for the 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.

  5. Update the application template and add the component:
    <h2 id="title">Welcome to Ember</h2>
    
    {{time-checker}}

    This will add the time-checker component to the application.

  6. Run the application and you'll see two times. The second time will update every second:
    How to do it...

    The Ember run loop makes this possible.

How it works...

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset