开发者

unable to cope with the asynchronous nature of navigator.geolocation

I'm using the navigator.geolocation.getCurrentPosition(function) api in firefox 3.6. When i try to call this method repeatedly I see that sometimes it works and sometimes it doesn't. I figured that the problem is because of its asynchronous callback nature. I can see that the callback function is being called at some point but my outer function is already exiting so i cannot catch the values of the position coordinates.

I'm pretty new to javascript so i'm assuming other javascript coders might have already figured out how to deal with it. Please help.

Edit: here's a sample piece of 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);
        }开发者_C百科);
       }
       return currLocation; // this returns undefined sometimes. I need help here
}    
</script>

Edit 2: Thanks everyone for answering, I wish i could choose all the answers as "accepted" but cannot do so.

Now I'm facing another problem. I'm calling the navigator.geolocation.getCurrentPosition every 3 seconds, but the responses stop after 10 - 15 replies. Any one got any idea ?

thanks again


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)  
});


Yes you have a problem with the callback nature of the operation. You cannot call the getCurrentLocation() function and expect that it will return synchronously. I am even surprised that it did work occasionally.

You have to use a slightly different paradigm when working with asynchronous calls. You should probably call 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 how the map parameter passed to the plotCurrentLocation() function is available to the inner functions within. This works because JavaScript has closures.


UPDATE:

The callback method suggested by the other answers is another option to tackle this, by adding another layer of abstraction.


You're trying to make it synchronous, and it won't work. As you've seen, there is no guarantee currLocation 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 the client code to:

getCurrentLocation(function(loc)
{
  //doSomethingWith loc
});


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>


You could 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 how to handle it (async/await, then(), whatever); for example

async componentDidMount(){

  position = await requestPosition();

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜