Unable to cope with the asynchronous nature of navigator.geolocation

I am using navigator.geolocation.getCurrentPosition (function) api in firefox 3.6. When I try to name this method many times, I see that sometimes it works, and sometimes not. I realized that the problem is with its asynchronous callback. I see that the callback function is being called at some point, but my external function is already exiting, so I cannot catch the position coordinates.

I'm new to javascript, so I guess other javascript coders might already figure out how to deal with this. Please, help.

Edit: here is the sample code I'm using

<script type="text/javascript"> function getCurrentLocation() { var currLocation; if(navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { currLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); }); } return currLocation; // this returns undefined sometimes. I need help here } </script> 

Edit 2: Thanks everyone for the answer, I would like all the answers to be โ€œacceptedโ€, but cannot do this.

Now I am facing another problem. I call navigator.geolocation.getCurrentPosition every 3 seconds, but the answers stop after 10-15 answers. Anyone got it?

thanks again

+5
source share
5 answers

Yes, you have a problem with the nature of the operation callback. You cannot call the getCurrentLocation() function and expect it to return synchronously. I am even surprised that it sometimes worked.

When working with asynchronous calls, you should use a slightly different paradigm. You should probably name your function plotCurrentLocation() and do something like the following example:

 function plotCurrentLocation(map) { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { var currLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); // plot the currLocation on Google Maps, or handle accordingly: new google.maps.Marker({ title: 'Current Location', map: map, position: currLocation }); map.setCenter(currLocation); }); } } 

Note that the map parameter passed to plotCurrentLocation() is available for internal functions inside. This works because JavaScript has closures .


UPDATE:

The callback method proposed by other answers is another option to solve this question by adding another level of abstraction.

+4
source

You are trying to make it synchronous and it will not work. As you saw, there is no guarantee that the function is set when the function returns. You probably now have something like:

 var loc = getCurrentLocation(); //doSomethingWith loc 

Change your function to:

 function getCurrentLocation(callback) { if(navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { callback(new google.maps.LatLng(position.coords.latitude, position.coords.longitude)); }); } else { throw new Error("Your browser does not support geolocation."); } } 

and client code:

 getCurrentLocation(function(loc) { //doSomethingWith loc }); 
+5
source

Better to use:

 <script type="text/javascript"> function getCurrentLocation(callback) { if(!navigator.geolocation) return; navigator.geolocation.getCurrentPosition(function(position) { var currLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); callback(currLocation); }); } </script> 

...

 <script type="text/javascript"> getCurrentLocation(function(currLocMap){ // do something with map now that it is ready.. }); </script> 
+3
source

You can use Promise:

 var lat,lon; var promise1 = new Promise(function(resolve, reject) { navigator.geolocation.getCurrentPosition(function(pos){ lat = pos.coords.latitude lon = pos.coords.longitude resolve({lat,lon}); }) }) promise1.then(function(value) { console.log(value.lat,value.lon) }); 
+2
source

You can also write a wrapper function for getCurrentPosition

 requestPosition() { // additionally supplying options for fine tuning, if you want to var options = { enableHighAccuracy: true, timeout: 5000, // time in millis when error callback will be invoked maximumAge: 0, // max cached age of gps data, also in millis }; return new Promise(function(resolve, reject) { navigator.geolocation.getCurrentPosition( pos => { resolve(pos); }, err => { reject (err); }, options); }); } 

This allows you to choose the processing method ( async/await , then() , etc.); eg

 async componentDidMount(){ position = await requestPosition(); } 

Isn't that great :-)

(Just wanted to add @AymanBakris to the answer, but all of this would be rather awkward in one comment ^^)

0
source

Source: https://habr.com/ru/post/1307911/


All Articles