-
Notifications
You must be signed in to change notification settings - Fork 5
/
geolocation-throttle.js
78 lines (71 loc) · 3.63 KB
/
geolocation-throttle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
(function(window) {
window.GeolocationThrottle = {
// a mapping of watchId => timeoutId that can be used to clear position watching
_timeoutIds: {},
/**
* Works just like navigator.geolocation.watchPosition, but adds one extra argument
* (throttleTime) to the options object, and makes sure that only one location callback
* is made per throttleTime timespan.
*
* Assumes that the browser supports navigator.geolocation, so one should still check for
* that. The single purpose of this lib is to throttle the location callbacks.
*/
watchPosition: function(callback, errorCallback, options) {
var throttleTime = (!options ? 0 : options.throttleTime || 0);
var bufferedArguments = null;
var lastCall = null;
var timeoutId = null;
var watchId = null;
watchId = navigator.geolocation.watchPosition(function() {
// update bufferedArguments
bufferedArguments = arguments;
if (!lastCall) {
//console.log("calling immediately initially");
lastCall = new Date();
callback.apply(this, arguments);
} else if (!timeoutId) {
// check if we've already passed the buffer time, in which case
// we'll call the callback immediately
if (new Date()-lastCall > throttleTime) {
//console.log("calling immediately since time has already passed");
lastCall = new Date();
callback.apply(this, arguments);
} else {
// if not enough time has passed since the last callback, we'll schedule
// a callback in the future
var that = this;
//console.log("call scheduled");
timeoutId = setTimeout(function() {
//console.log("Call");
lastCall = new Date();
callback.apply(that, bufferedArguments);
timeoutId = null;
window.GeolocationThrottle._timeoutIds[watchId] = null;
}, throttleTime - (new Date()-lastCall));
// we store the timeout id so that we can clear the timeout if clearWatch
// is called before the setTimeout fires
window.GeolocationThrottle._timeoutIds[watchId] = timeoutId;
}
} else {
// we already have a scheduled call
//console.log("skipping call");
}
}, errorCallback, options);
return watchId;
},
/**
* Calls navigator.geolocation.clearWatch for the given watchId, but also
* clears any timeout that has been set up by GeolocationThrottle to make
* sure that no more callback for this watchId is called.
*/
clearWatch: function(watchId) {
navigator.geolocation.clearWatch(watchId);
// if there's a scheduled watch position callback we'll clear it
var timeoutId = window.GeolocationThrottle._timeoutIds[watchId];
if (timeoutId) {
clearTimeout(timeoutId);
window.GeolocationThrottle._timeoutIds[watchId] = null;
}
}
};
})(window);