corvid
corvid

Reputation: 11197

Making a callback in a mousemove handler asynchronous

I have the following event handler. Due to their frequency with which it occurs, it will be pretty "greedy". onMouseMove, it will draw a "lasso" around the selected area, then perform a throttled geospatial search around the area.

onMouseMove = ({ pageX, pageY }: MouseEvent) => {
  const lasso = this.getLasso(pageX, pageY);
  this.ctx.setLineDash([6]);
  this.ctx.strokeStyle = '#ffffff';
  this.ctx.strokeRect(lasso.left, lasso.top, lasso.width, lasso.height);

  // this is the problem area.
  this.props.onSelection(this.search(lasso));
}

However, I find the callstack is largely just about running this callback. The action to update the "lasso" is only 2ms, but the onSelection callback takes ~40ms. They're both grouped under Event (mousemove) in performance. I think this is making the animation of the lasso look very choppy.

enter image description here

Would there be a way to run this callback independently/asynchronously from the mouse event handler? It doesn't so much matter to the mousemove event when it completes.

Upvotes: 1

Views: 736

Answers (1)

jpaugh
jpaugh

Reputation: 7035

Use setTimeout with a delay of 0. It will be added to the JavaScript scheduler queue, and run after the current callstack finishes.

In situ, this becomes:

onMouseMove = ({ pageX, pageY }: MouseEvent) => {
  const lasso = this.getLasso(pageX, pageY);
  this.ctx.setLineDash([6]);
  this.ctx.strokeStyle = '#ffffff';
  this.ctx.strokeRect(lasso.left, lasso.top, lasso.width, lasso.height);

  // this is the problem area.
  setTimeout(function () { this.props.onSelection(this.search(lasso));});
}

Since 0 is the default, you may omit it, as shown in the linked docs:

If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, as soon as possible. Note that in either case, the actual delay may be longer than intended; see Reasons for delays longer than specified below.

Upvotes: 3

Related Questions