Are the Ember.run functions intended to replace setTimout?


#1

I have a slider UI which sets a value on a query param. Everything works great other than the massive number of server queries that fire as I slide the bar and the property changes. Historically, I would have used a setTimeout() and waited to fire of the server request until at 200ms or so has elapsed without a change in value.

import Ember from 'ember';

export default Ember.Component.extend({
  min: null,
  max: null,
  populateValues: function() {
    if(Ember.isEmpty(this.get('min'))) { this.set('min', 0); }
    if(Ember.isEmpty(this.get('max'))) { this.set('max', 100); }
  }.on('willInsertElement'),
  
  addSlider: function() {
    var component = this;
    var elem = component.$()[0];
    var timer = null;

    Ember.$(elem).find('.slider').slider({
      ticks: [0, 20, 40, 60, 80, 100],
      ticks_labels: ['0','20','40','60','80','100'],
      value: [ parseInt(component.get('min')), parseInt(component.get('max')) ],
      ticks_snap_bounds: 5
    }).on('change', function(evt) {
      if(timer) { 
        clearTimeout(timer);
        timer = null;
      }
      timer = setTimeout(function() {
        component.sendAction('onScoreChanged', evt.value.newValue[0], evt.value.newValue[1]);
      }, 200);
    });
  }.on('didInsertElement')
});

onScoreChanged updates a property on the controller which updates a queryParam on the route which fires a query against the server…

So the question is whether one of the functions under Ember.run intended to replace this kind of use of setTimeout?

Or, more generally, is there an “Ember way” of doing this?


#2

You might be interested in my recent post for “auto-saving”. Basically, I’d recommend using Ember.run.debounce(): http://emberjs.com/api/classes/Ember.run.html#method_debounce


#3

That worked great. Because I didn’t need to worry about a different submit action, it ended up being as simple as:

  sendScores: function() {
    var min = this.get('min'),
        max = this.get('max');
    console.log('sending action...'+ min +", "+ max);
    this.sendAction('onScoreChanged', min, max);
  },
  
  addSlider: function() {
    var component = this;
    var elem = component.$()[0];
    Ember.$(elem).find('.slider').slider({
      ticks: [0, 20, 40, 60, 80, 100],
      ticks_labels: ['0','20','40','60','80','100'],
      value: [ parseInt(component.get('min')), parseInt(component.get('max')) ],
      ticks_snap_bounds: 5
    }).on('change', function(evt) {
      console.log('changed...');
      component.set('min', evt.value.newValue[0]);
      component.set('max', evt.value.newValue[1]);
      Ember.run.debounce(component, component.sendScores, 333);
    });
  }.on('didInsertElement')