I'd like to use the HTML5 GeoLocation API to retrieve my longitude and latitude and manage the request using a jQuery Deferred object.
Here is what my code looks like:
var geoLocation = {
getLocation: function() {
// create deferred object
var deferred = $.Deferred();
// if geo location is supported
if(navigator.geolocation) {
// get current position and pass the results to this.geoLocationSuccess or time out after 5 seconds if it fails
navigator.geolocation.getCurrentPosition(this.geoLocationSuccess, this.geoLocationError, {
timeout: 5000
});
} else {
// geo location isn't supported
console.log('Your browser does not support Geo Location.');
}
},
geoLocationSuccess: function(position) {
// resolve deffered object
deferred.resolve(position.coords.latitude, position.coords.longitude);
// return promise
return deferred.promise();
},
geoLocationError: function() {
console.log('Geo Location failed.');
}
};
And here is my Deferred object:
$.when(geoLocation.getLocation()).then(function(data, textStatus, jqXHR) {
console.log(data);
});
I'm expecting the longitude and latitude to be returned by the then()
callback but instead, I get the error that deferred
is undefined. I think it has something to do with the scope of where I define my deferred object but I'm not sure. What am I missing?
Michael, after reading Hackaholic's answer and your own, both will work with regard to handling successfully returned data, but errors could be better handled.
If navigator.geolocation.getCurrentPosition()
fails, it will pass a potentially informative PositionError object to its error handler. This object, which can be passed down the promise chain and handled in the calling function, is disregarded in both answers.
Similarly, promise rejection can also be used to pass your own "Your browser does not support Geo Location" error down the promise chain.
var geoLocation = {
getLocation: function() {
var deferred = $.Deferred();
if(navigator.geolocation) {
// geo location is supported. Call navigator.geolocation.getCurrentPosition and :
// - resolve the promise with the returned Position object, or
// - reject the promise with the returned PositionError object, or
// - time out after 5 seconds
navigator.geolocation.getCurrentPosition(deferred.resolve, deferred.reject, { timeout: 5000 });
} else {
//geo location isn't supported
//Reject the promise with a suitable error message
deferred.reject(new Error('Your browser does not support Geo Location.'));
}
return deferred.promise();
}
};
Ignoring the comments, this is very compact and note how geoLocation.getLocation()
makes no attempt to handle errors but makes them available to the calling function's error handler.
Now, $.when()
is not necessary because your geoLocation.getLocation()
function returns a promise which has its own .then()
method. It is already "thenable" without $.when()
.
geoLocation.getLocation().then(function(position) {
console.dir(position);
}).fail(function(err) {
console.error(err);
});
Thus, you fully exploit the ability of the promise to handle success or failure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With