可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Inside my handlebars template:
Today's date: {{currentDate}}
Current Time: {{currentTime}}
Inside my helpers:
Ember.Handlebars.registerBoundHelper 'currentDate', (option) ->
moment().format('LL');
Ember.Handlebars.registerBoundHelper 'currentTime', (option) ->
moment().format('h:mm:ss a');
How would I go about updating the currentTime to the view every 1 second?
I have read the Ember recommends Ember.run.later
but I can't quite figure out where to put it and how to call it using this helper.
回答1:
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).
回答2:
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
回答3:
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);
},
回答4:
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);
}
回答5:
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/