Reputation: 4515
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.
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....
See answer below.
Upvotes: 0
Views: 2067
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);
});
Upvotes: 2