无法应对 navigator.geolocation 的异步特性

IT技术 javascript geolocation w3c
2021-02-25 11:40:21

我在 firefox 3.6 中使用 navigator.geolocation.getCurrentPosition(function) api。当我尝试重复调用此方法时,我发现有时它起作用,有时不起作用。我认为问题在于它的异步回调特性。我可以看到回调函数在某个时候被调用,但我的外部函数已经退出,所以我无法捕捉位置坐标的值。

我对 javascript 很陌生,所以我假设其他 javascript 编码人员可能已经想出了如何处理它。请帮忙。

编辑:这是我正在使用的一段示例代码

<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>

编辑2:感谢大家的回答,我希望我可以选择所有的答案为“接受”,但不能这样做。

现在我面临另一个问题。我每 3 秒调用一次 navigator.geolocation.getCurrentPosition,但响应在 10 - 15 条回复后停止。任何人有任何想法吗?

再次感谢

5个回答

您可以使用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)  
});
很好的建议,应该推高。
2021-04-26 11:40:21

是的,您对操作的回调性质有疑问。您不能调用该getCurrentLocation()函数并期望它会同步返回。我什至很惊讶它偶尔会起作用。

在处理异步调用时,您必须使用稍微不同的范例。您可能应该调用您的函数,plotCurrentLocation()并执行类似于以下示例的操作:

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

请注意map传递给plotCurrentLocation()函数参数如何可供内部函数使用。这是有效的,因为 JavaScript 有闭包


更新:

其他答案建议的回调方法是通过添加另一层抽象来解决此问题的另一种选择。

嘿!感谢您的回复。我解决了这个问题。现在我开始了解 javascript 的本质。我还有一个问题,对可以调用 navigator.geolocation.getCurrentPostion 的次数是否有限制,因为我试图每 3 秒调用一次,并且响应在 10 或 15 次尝试后停止。你有什么主意吗
2021-04-27 11:40:21
@Raja:不,我不知道任何此类限制。地理定位仍然是新事物。也许您可以在 Stack Overflow 上发布关于此问题的另一个问题。
2021-05-10 11:40:21

你试图让它同步,但它不会工作。如您所见,不能保证在函数返回时设置 currLocation。你现在可能有这样的事情:

var loc = getCurrentLocation();
//doSomethingWith loc

将您的功能更改为:

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

和客户端代码:

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

更好地使用:

<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>

你也可以写一个包装函数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);
  });
}

这允许您选择如何处理它(async/awaitthen(),等等); 例如

async componentDidMount(){

  position = await requestPosition();

}

是不是很漂亮:-)

(只是想添加到@AymanBakris 的答案中,但所有这些在一个评论中都会很尴尬^^)