Reputation: 790
I have this module that wraps a call to an asynchronous method to watch for changes in the browser's geolocation navigator.geolocation.watchPosition
var geo_value;
//Initialises the devices geolocation
navigator.geolocation.watchPosition(function (position) {
geo_value = position.coords.longitude + "," + position.coords.latitude;
});
Everytime the watchPosition
method call fires, I store the value in a variable to provide me programmatic access to the currentPosition
at any given time.
This all works fine, however I now want to expose this currentPosition
via a custom async method that I am exporting from my module.
define(["global"], function (window) {
var navigator = window.navigator;
var geo_value;
//Initialises the devices geolocation
navigator.geolocation.watchPosition(function (position) {
geo_value = position.coords.longitude + "," + position.coords.latitude;
});
return {
currentPosition: function (callback) {
setTimeout(function () {
while (!geo_value) {
//keep looping until geo_value has been initially set by the watch position above
}
//geo_value has been set, execute callback
callback(geo_value);
}, 0);
}
};
});
I have made the module
expose the currentPosition
, which works if geo_value
has already been set, but I also want it to wait asynchronously if geo_value
hasn't been set and then execute the callback when the watchPosition
finally sets a value for geo_value
. I tried using the setTimeout
function to attempt at making it asynchronous, but it didn't work.
Please any help will be much appreciated.
Upvotes: 0
Views: 6538
Reputation: 3442
This code below blocks other code to be executed as JavaScript only has one thread of execution:
while (!geo_value) {
//keep looping until geo_value has been initially set by the watch position above
}
Instead try something like this:
currentPosition: function(callback) {
if (geo_value) {
callback(geo_value);
} else {
// try again 1 sec later
setTimeout(this.currentPosition.bind(this, callback), 1000);
}
}
Upvotes: 0
Reputation: 211942
So, Javascript is really a single-threaded event loop. Getting a feel for what exactly that means will take experience.
In this case, it means that your while loop will never terminate, because nothing else can happen while it's running.
One better way to do this is to call the callbacks you're getting as params to currentPosition when watchPosition is called.
define(["global"], function (window) {
var navigator = window.navigator,
geo_value,
callbacks = [],
//Initialises the devices geolocation
navigator.geolocation.watchPosition(function (position) {
geo_value = position.coords.longitude + "," + position.coords.latitude;
// Update all callbacks with new value.
for (var i = 0; i < callbacks.length; i++) {
callbacks[i](geo_value);
}
});
return {
onCurrentPosition: function (callback) {
callbacks.push(callback)
}
};
});
Upvotes: 2
Reputation: 7452
define(["global"], function (window) {
var navigator = window.navigator;
var geo_value;
var cb;
//Initialises the devices geolocation
navigator.geolocation.watchPosition(function (position) {
geo_value = position.coords.longitude + "," + position.coords.latitude;
if (cb) {
cb(geo_value);
cb = null;
}
});
return {
currentPosition: function (callback) {
if (geo_value) {
callback(geo_value);
} else {
cb = callback;
}
};
});
Upvotes: 1