SetTimeout vs. Ember.run.later in an ember app?

南楼画角 提交于 2019-12-02 22:04:45
Toran Billups

You can use Ember.run.later like you would normally use setTimeout

Ember.run.later((function() {
  //do something in here that will run in 2 seconds
}), 2000);

I'm not sure of the internals, but I know that integration testing Ember requires that you use run.later (if you don't the test code won't wait for the timeout to finish).

You won't want to add the timeout into the helper, you'll want to add it to a global variable and just do a diff from it. The reason you'll want to use Em.run.later is it will inject it into the run loop (part of what Toran was getting at). This is really important for testing.

Add the time to a global variable

App.ApplicationRoute = Em.Route.extend({
  setupController: function(controller, model){
    this._super(controller, model);
    this.startWatchingTime(controller);
  },
  startWatchingTime: function(controller){
    var self = this;
    controller.set('currentTime', moment());
    Em.run.later(function(){
      self.startWatchingTime(controller);
    }, 1000);
  }
});

Add it to the helper

Ember.Handlebars.helper('time-diff', function(date1, date2, format, options) {
  return date1.diff(date2, format);
});

send it into the helper

{{time-diff  controllers.application.currentTime anotherTime 'seconds'}}

http://emberjs.jsbin.com/UcUrIQa/1/edit

you want to use Embers.run loop instead of going outside with setTimer.

The current (today) version of ember requires this format with context this (updating Toran Billups answer)

this._debouncedItem = Ember.run.later(this, () => {
   debugger;
}, 5000);

I highly recommend keeping a reference to the response of later() and cancelling it in the destroy hook

destroy() {
   this._super(...arguments);
   Ember.run.cancel(this._debouncedItem);
},
Miguel Madero

You could make currentDate a regular property

currentDate: null,
currentTime: null

You can start this timer in the controller's constructor.

init: function () { 
  this.updateTimeProperty();
},
updateTimeProperty: function () {
  var _this = this;
  Ember.run.later(this, function() {
    _this.currentDate = moment().format('LL');
    _this.set('currentTime',  moment().format('h:mm:ss a');
    _this.updateTimeProperty());
  }, 1000);
}

I'm bit outdated Ember user, but I would do it like this hope there is a better solution.

App.CurrentTimeView = Ember.View.extend({
    template : Ember.Handlebars.compile("<span>{{view.currentTime}}</span>"),
    currentTime : null,
    init : function(){
        var view = this;
        view.set('currentTime', moment().format('h:mm:ss a'));
        setInterval((function(view){
            return function(){view.set('currentTime', moment().format('h:mm:ss a'));};
        })(view),1000);
    }
});

and in the template

{{view "App.CurrentTimeView"}}

To answer your question, Javascript has a single threaded execution (unless you use webworkers) which means it will do things one by one in a serial manner. When you use setInterval it will en-queue your function every x milliseconds into this main execution queue. setInterval uses the passed time to do its queuing. Ember run loops will kind of calculate bindings and other heavy things in each run loop, so at the end of the loop we are sure that out changes are there ready. There are hooks like Em.run.next to make sure those codes when being run will have the complete changes done in last run loop. Similarly when you pass a time to Em.run.later it will as well run after that much time and also supports a parameter to set this inside the function. Mostly when dealing with some variables or Model/Controller data inside the function.

In your case setInterval looks ok (for me).

http://jsfiddle.net/NQKvy/604/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!