Search code examples
javascriptcordovaember.jsember-cli

Ember CLI async initializers & cordova readiness


Using ember cli v0.1.4, ember 1.8.1 & cordova 3.7, I'm utilizing initializers to wait for the device to be ready;

var CordovaInitializer = {
  name: 'waitForCordova',
  before:'i18n',

  initialize: function(Container, App) {

    if(window.cordova) {
      console.log('defering app launch until cordova is ready...');
      App.deferReadiness();

      document.addEventListener('deviceready', function(){
        console.log('lift off!');

        App.advanceReadiness();
      }, false);
    }
  }
};

export default CordovaInitializer;

My second initialzer needs to wait for cordova app readiness too -

export default {
  name: 'i18n',
  after:'waitForCordova',

  initialize: function(Container, App) {

     console.log('initializing translations'); 

     /* snip */
  } 

};

I am expecting the following output -

$ defering app launch until cordova is ready...
$ lift off!
$ initializing translations

However, I am getting the following -

$ defering app launch until cordova is ready...
$ initializing translations
$ lift off!

How can I get my second initializer to wait until cordova is loaded? They're firing in the correct order, but I was expecting the second one to wait for App.advanceReadiness.

Essentially I need an async initializers as described here - ember initializers followed by a second adapter that waits for the first to complete.


Solution

  • Note: This answer was updated. Check the update below

    ========================Old Answer=========================

    You can utilize Ember.Instrumentation to sync your initializers

    // app/initializers/cordova.js
    
    import Ember from 'ember';
    
    var CordovaInitializer = {
      name: 'waitForCordova',
      before: 'i18n',
      initialize: function(container, application) {
        application.set('shouldSubscribeCordovaDeviceReady', false);
        if (window.cordova) {
          console.log('defering app launch until cordova is ready...');
    
          application.set('shouldSubscribeCordovaDeviceReady', true);
          application.deferReadiness();
    
          document.addEventListener('deviceready', function() {
            console.log('lift off!');
            Ember.Instrumentation.instrument('cordova:deviceready', null, Ember.K);
            application.set('shouldSubscribeCordovaDeviceReady', false);
            application.advanceReadiness();
          }, false);
        }
      }
    };
    
    export
    default CordovaInitializer;
    
    // app/initializers/i18n.js
    
    import Ember from 'ember';
    
    var initializeI18n = function(container, application) {
      console.log('initializing translations');
      //do your thing
    };
    
    export
    default {
      name: 'i18n',
      after: 'waitForCordova',
      initialize: function(container, application) {
        var subscriber;
        if (application.get('shouldSubscribeCordovaDeviceReady')) {
          application.deferReadiness();
          subscriber = Ember.Instrumentation.subscribe('cordova:deviceready', {
            before: Ember.K,
            after: function() {
              initializeI18n(container, app);
              application.advanceReadiness();
              Ember.Instrumentation.unsubscribe(subscriber);
            }
          });
        } else {
          initializeI18n(container, application);
        }
      }
    };
    

    ========================End of Old Answer====================

    ===================Updated Answer===================

    In order to sync your initializers, you can extend the Ember.Application class with Ember.Evented. In this way, the application instance will have pubsub capabilities.

    // app/app.js
    
    import Ember from 'ember';
    
    // ...
    
    var App;
    
    App = Ember.Application.extend(Ember.Evented, {
    
      // ...  
    
    });
    
    // ...
    
    export default App;
    
    // app/initializers/cordova.js
    
    import Ember from 'ember';
    
    var CordovaInitializer = {
      name: 'waitForCordova',
      before: 'i18n',
      initialize: function(registry, application) {
        application.set('shouldSubscribeCordovaDeviceReady', false);
        if (window.cordova) {
          console.log('defering app launch until cordova is ready...');
    
          application.set('shouldSubscribeCordovaDeviceReady', true);
          application.deferReadiness();
    
          document.addEventListener('deviceready', function() {
            console.log('lift off!');
            application.trigger('cordova:deviceready');
            application.set('shouldSubscribeCordovaDeviceReady', false);
            application.advanceReadiness();
          }, false);
        }
      }
    };
    
    export
    default CordovaInitializer;
    
    // app/initializers/i18n.js
    
    import Ember from 'ember';
    
    var initializeI18n = function(container, application) {
      console.log('initializing translations');
      //do your thing
    };
    
    export
    default {
      name: 'i18n',
      after: 'waitForCordova',
      initialize: function(registry, application) {
        if (application.get('shouldSubscribeCordovaDeviceReady')) {
          application.deferReadiness();
          application.one('cordova:deviceready', null, function() {
            initializeI18n(container, app);
            application.advanceReadiness();
          });
        } else {
          initializeI18n(container, application);
        }
      }
    };