CartoDB / torque

Temporal mapping for CARTO
http://cartodb.github.com/torque/
BSD 4-Clause "Original" or "Old" License
397 stars 129 forks source link

Torque throws "start must be smaller than end" when the query's result is empty #259

Open clementprdhomme opened 8 years ago

clementprdhomme commented 8 years ago

Hi guys!

I've ran into a case where, when the query we pass to Torque doesn't return any row, the library throws the following error instead of not doing anything:

start must be smaller than end

In this case, the JSONP request returns the following properties:

{
  "metadata": {
    "torque": {
      "start": 0,
      "end": 0
    }
  }
}

and the AnimatorStepsRange throws the error on that line.

I've temporarily hidden the error by overriding the library with the following code, but I wonder if you could take a look at this to avoid throwing a misleading error:

/* We define the new AnimatorStepsRange to avoid the error message */
const CustomAnimatorStepsRange = function(start, end) {
  if (start < 0) throw new Error('start must be a positive number');
  /* The only change is on the next line where ">=" has been replaced by ">" */
  if (start > end) throw new Error('start must be smaller than end');
  this.start = start;
  this.end = end;
};

CustomAnimatorStepsRange.prototype = {
  diff: function() { return this.end - this.start; },
  isLast: function(step) { return (step | 0) === this.end; }
};

/* We create the layer */

const layer = new L.TorqueLayer({
  user: 'myUser',
  table: 'myTable',
  sql: 'myQueryWithNoResult',
  cartocss: 'myCartoCSS'
});

/* We override here two methods to use our custom AnimatorStepsRange */

layer.animator.steps = function(_) {
  this.options.steps = _;
  this._defaultStepsRange = new CustomAnimatorStepsRange(0, _);
  return this.rescale();
};

layer.animator.stepsRange = function(start, end) {
  if (arguments.length === 2) {
    if (start < this._defaultStepsRange.start) throw new Error('start must be within default steps range');
    if (end > this._defaultStepsRange.end) throw new Error('end must be within default steps range');
    this._customStepsRange = new CustomAnimatorStepsRange(start, end);
    this.options.onStepsRange && this.options.onStepsRange();
    var step = this.step() | 0;
    if (step < start || step > end) {
      this.step(start);
    }
  }
  return this._customStepsRange || this._defaultStepsRange;
};

Thanks, Clément