Cokorda Raka
Cokorda Raka

Reputation: 4515

lodash debounce not-working (I use it wrongly?), function called multiple times

UPDATE: Answered by myself. Scroll to the end.

My objetive is simple:

I have a google map canvas. User can drag the map, and the program automatically downloads the incidents around the center of the map (and draw the markers).

I have this listener for plugin.google.maps.event.CAMERA_CHANGE events. The thing is, this listener triggers multiple times. Meaning: from the time you tap your finger on the canvas -> dragging in accros the canvas -> to the time you lift your finger ... the event triggers multiple times. Not just when you lift your finger. Apparently it has a watcher that triggers every N miliseconds.

I dont't want my code to perform that costly downloading data from the server + drawing markers during those interim camera_changes. I want to do it only after the user stop dragging. That means: on the last camera change event received during 5 seconds (I figured that the slowest user takes 5 seconds to drag from corner to the opposite corner of the canvas).

Obviouly I turn to debounce for this need. But it doesn't seem to work. I can see from the logs (X1, X2).... that the function gets called multiple times (around 3-to-4 times, depends on how fast you drag across the canvas).

Indeed, they get called only after I stop dragging. But, they get called in series. All 3-4 of them. With delay of 5 seconds between invocation.

That's not what I expected. I also added invocation to the .cancel method (which I think is superfluous..., because if I understand it correctly, the debounce should've already handled that; cancelling interim-invocations within the timeout).

I also tried throttle (which I think conceptually is not the answer. Debounce should be the answer). Anyway, same issue with throttle.

So, my question: where did I do wrong (in using lodash's debounce)?

Thanks!

        var currentPosition = initialPosition();
        drawMarkersAroundCenter(map, currentPosition);

        var reactOnCameraChanged = function(camera) {
          console.log('X1');

          console.log('-----');
          console.log(JSON.stringify(camera.target));
          console.log(JSON.stringify(currentPosition));
          console.log('-----');

          if (camera.target.lat == currentPosition.lat && camera.target.lng == currentPosition.lng) {
            return;
          }

          currentPosition = camera.target;
          drawMarkersAroundCenter(map, currentPosition);
        }

        var debouncedReactOnCameraChange = lodash.debounce(reactOnCameraChanged, 5000, {
          'leading': false,
          'trailing': true
        });

        map.on(plugin.google.maps.event.CAMERA_CHANGE, function(camera) {
          debouncedReactOnCameraChange.cancel();
          debouncedReactOnCameraChange(camera);
        });

--- UPDATE ---

I tried a very simplified scenario of using debounce on nodejs console, it works as I expected. I don't even invoke .cancel in the code below. So what's wrong with the above code? I can't see any difference with this simplified code in the image below.

enter image description here

UPDATE

I tried with this dude method instead of "reactOnCameraChanged":

        var dude = function(camera) {
          console.log('dude');
        }

        var debouncedReactOnCameraChange = lodash.debounce(dude, 5000, {
          'leading': false,
          'trailing': true
        });

And I also removed the invocation to .cancel:

        map.on(plugin.google.maps.event.CAMERA_CHANGE, function(camera) {
          //debouncedReactOnCameraChange.cancel();
          debouncedReactOnCameraChange(camera);
        });

I can see the 'dude' gets printed only once during those 5 seconds.... So.., something that I do inside reactOnCameraChanged is causing interference ... somehow....

RESOLVED:

See answer below.

Upvotes: 0

Views: 2067

Answers (1)

Cokorda Raka
Cokorda Raka

Reputation: 4515

This code works:

        var currentPosition = latLng;
        drawMarkersAroundCenter(map, currentPosition);

        var debouncedReactOnCameraChange = lodash.debounce(function(camera) {
          console.log('reactOnCameraChanged: ' + JSON.stringify(currentPosition));
          drawMarkersAroundCenter(map, currentPosition);
        }, 3000, {
          'leading': false,
          'trailing': true
        });

        map.on(plugin.google.maps.event.CAMERA_CHANGE, function(camera) {
          console.log('CAMERA_CHANGE');

          if (camera.target.lat == currentPosition.lat && camera.target.lng == currentPosition.lng) {
            console.log('same camera spot');
            return;
          }

          console.log('different camera spot');

          currentPosition = camera.target;
          debouncedReactOnCameraChange(camera);
        });

enter image description here

Upvotes: 2

Related Questions