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

发布于 2024-08-30 07:56:20 字数 875 浏览 8 评论 0原文

我在 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 个回复后停止。有人知道吗?

再次感谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

十秒萌定你 2024-09-06 07:56:20

您可以使用承诺:

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

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)  
});
梦罢 2024-09-06 07:56:20

是的,您对操作的回调性质有疑问。您不能调用 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 有闭包


更新:

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

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.

七七 2024-09-06 07:56:20

你试图让它同步,但它不会起作用。正如您所看到的,不能保证 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
});

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
});
软甜啾 2024-09-06 07:56:20

更好地使用:

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

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>
隔纱相望 2024-09-06 07:56:20

您还可以为 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();

}

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文