Nicos Karalis
Nicos Karalis

Reputation: 3773

SetTimeout inside emberjs model

I have in my emberjs application a model that doesn't has any database data. I have create this model because i want some object that pools some requests from the server but is not binded to a controller or view.

something like: StatusChecker

inside my Application.create i do like this:

Webapp = Ember.Application.create({
  rootElement: '#content',
  LOG_TRANSITIONS: true,

  ready: function() {
    return Webapp.status_helper = Webapp.StatusHelper.create({
      timer: 15
    });
  }
});

this will instantiate a Webapp.StatusHelper object that must be unique for the application. when i call init on this object i also start the polling using a default timer:

Webapp.StatusHelper = Ember.Object.extend({
  init: function(params) {
    this.timer = this.get("timer");
    this.timeoutID = null;
    this.controller = null;
    this.start();
  },
  start: function() {
    this.execute();
  },
  stop: function() {
    clearTimeout(this.timeoutID);
  },
  setTimer: function(newTime) {
    this.stop();
    this.timer = newTime;
    this.start();
  },
  execute: function() {
    var $this = this;
    this.stop();
    $.get("/status").done(function(data) {
      console.log(data);

      if (data["status"] === 0) { // Continue trying
        $this.timeoutID = setTimeout(function() {
          $this.execute();
        }, $this.timer * 1000);
      } else if (data["status"] === 1) { // Go to a given controller
        $this.setTimer(15);
        $this.transitionToRoute('index'); // This doesn't work
      } else {
        $this.setTimer(15);
        $this.transitionToRoute('problem'); // This doesn't work
      }
    });
  }
});

The first problem is that i cant change routes from the model using this: $this.transitionToRoute('problem');. is there a way to do it from model?

the second problem is that sometimes when i get into a controller i need to specify the interval for the StatusHelper right after i need to stop that timer and start it with another interval, like this:

Webapp.IndexRoute = Ember.Route.extend
  setupController: (controller) ->
    Webapp.status_helper.setTimer 15

Webapp.ProblemRoute = Ember.Route.extend
  setupController: (controller) ->
    Webapp.status_helper.setTimer 1

this happens because i need to check if the problem was solved every second, and the index page transitions to problem page whenever it needs. After the transition i get 2, and sometimes more, intervals working on the same job.

how can i stop it and make only one function to work?

P.S.: If you find that i need to change the model with something else i can change it.


tl;dr


EDIT

Version of my libraries:

DEBUG: Ember.VERSION : 1.0.0-rc.1 ember.js:348
DEBUG: Handlebars.VERSION : 1.0.0-rc.3 ember.js:348
DEBUG: jQuery.VERSION : 1.9.1 

Upvotes: 0

Views: 938

Answers (1)

Mike Grassotti
Mike Grassotti

Reputation: 19050

The first problem is that i cant change routes from the model using this: $this.transitionToRoute('problem');. is there a way to do it from model?

You can't/shouldn't access the router from a model. Whenever you find it necessary to do so it's a clue that maybe the code your writing should not be a model. In this case Webapp.StatusHelper a should really be a controller. So something like:

Webapp.StatusController = Ember.Controller.extend({
  //your code here
});

Then you can get rid of the init() App.ready() hook and instead use setupController hook of your ApplicationRoute to configure and start the timer. And of course since you're now in a controller you will be able to access the router.

how can i stop it and make only one function to work?

So basically you need to start/stop the timer when transitioning to new routes. Use the route's activate, deactivate, and setupController hooks to turn timer on/off when routes change. This way you can ensure that the timer is only running when you want it to.

Webapp.IndexRoute = Ember.Route.extend
  activate: (controller) ->
    this.controllerFor('status').setTimer 15
    this.controllerFor('status').start()

  deactivate: (controller) ->
    this.controllerFor('status').stop()

Webapp.IndexRoute = Ember.Route.extend
  activate: (controller) ->
    this.controllerFor('status').setTimer 1
    this.controllerFor('status').start()

  deactivate: (controller) ->
    this.controllerFor('status').stop()

Upvotes: 2

Related Questions