web-dev-qa-db-ja.com

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

ハンドルバーテンプレート内:

Today's date: {{currentDate}}
Current Time: {{currentTime}}

私のヘルパーの中:

Ember.Handlebars.registerBoundHelper 'currentDate', (option) ->
  moment().format('LL');

Ember.Handlebars.registerBoundHelper 'currentTime', (option) ->
  moment().format('h:mm:ss a');

1秒ごとにcurrentTimeをビューに更新するにはどうすればよいですか?

Ember推奨 Ember.run.later しかし、私はそれをどこに置くか、このヘルパーを使用してそれをどのように呼び出すかを理解することはできません。

26
Blair Anderson

通常はsetTimeoutを使用するように、Ember.run.laterを使用できます。

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

内部についてはよくわかりませんが、統合テストEmberではrun.laterを使用する必要があります(テストコードがタイムアウトしない場合、タイムアウトが終了するのを待たない)。

53
Toran Billups

ヘルパーにタイムアウトを追加する必要はありません。グローバル変数にタイムアウトを追加し、それから差分を行うだけです。使用する理由Em.run.laterは、それを実行ループ(Toranが取得していたものの一部)に挿入します。これはテストにとって本当に重要です。

グローバル変数に時間を追加します

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);
  }
});

ヘルパーに追加します

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

ヘルパーに送ります

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

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

12
Kingpin2k

setTimerを使用して外に出るのではなく、Embers.runループを使用します。

現在の(今日の)バージョンemberはcontextthis(Toran Billupsの回答を更新)でこの形式を必要とします)

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

Later()の応答への参照を保持し、destroyフックでキャンセルすることを強くお勧めします

destroy() {
   this._super(...arguments);
   Ember.run.cancel(this._debouncedItem);
},
6
mihai

currentDateを通常のプロパティにすることができます

currentDate: null,
currentTime: null

このタイマーは、コントローラーのコンストラクターで開始できます。

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);
}
2
Miguel Madero

私は少し時代遅れですEmberユーザーですが、より良い解決策があることを願ってこのようにします。

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);
    }
});

およびテンプレート内

{{view "App.CurrentTimeView"}}

あなたの質問に答えるために、Javascriptには単一のスレッド実行があります(Webworkersを使用しない限り)。つまり、逐次的に1つずつ処理します。 setIntervalを使用すると、xミリ秒ごとに関数がこのメイン実行キューに入れられます。 setIntervalは、渡されたtimeを使用してキューイングを行います。 Ember実行ループは、各実行ループでバインディングやその他の重いことを計算します。そのため、ループの最後に、変更が準備できていることを確認します。Em.runのようなフックがあります。同様に、Em.run.laterに時間を渡すと、その時間後に実行され、thisを設定するパラメーターもサポートされます。ほとんどの場合、関数内のいくつかの変数またはモデル/コントローラーデータを処理する場合。

あなたの場合、setIntervalはOKに見えます(私にとって)。

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

1
sabithpocker