我有一个很简单的JS使用navigator。geolocation。getcurrentposition jammy。
$(document).ready(function(){
$("#business-locate, #people-locate").click(function() {
navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
});
navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
function foundLocation(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
var userLocation = lat + ', ' + lon;
$("#business-current-location, #people-current-location").remove();
$("#Near-Me")
.watermark("Current Location")
.after("<input type='hidden' name='business-current-location' id='business-current-location' value='"+userLocation+"' />");
$("#people-Near-Me")
.watermark("Current Location")
.after("<input type='hidden' name='people-current-location' id='people-current-location' value='"+userLocation+"' />");
}
function noLocation() {
$("#Near-Me").watermark("Could not find location");
$("#people-Near-Me").watermark("Could not find location");
}
})//end DocReady
基本上,这里发生的事情是我们得到当前位置,如果它得到了,两个“水印”被放置在两个字段中,表示“当前位置”,两个隐藏字段被创建,并使用latong数据作为它们的值(它们在开始时被删除,这样它们就不会每次都重复)。还有两个按钮,它们有一个点击功能,做同样的事情。
不幸的是,每隔三次左右,它就会奏效。
这里有什么问题?
大家也一样,顺便说一句,这在Chrome(稳定,开发和金丝雀)中工作完美,只是在FF和Safari中不合适。它在我的iPhone和iPad上也很好用(Safari!)这可能是由于这个功能相对较新(即它是一个bug)。我现在花了差不多一个星期的时间在这个上面,我就是不能让它在那些浏览器上工作
以下是我的发现:
第一次调用getCurrentPosition时,它工作得很完美。任何后续调用都不会返回,也就是说,它不会触发successCallback或errorCallback函数。为了证明我的观点,我在看涨期权中添加了几个仓位选项:
navigator.geolocation.getCurrentPosition(successCallback, errorCallback, {timeout: 10000});
并且每次都超时(在第一次成功调用之后)。我认为我可以用maximumAge来修复它,但这似乎并不像它应该工作的那样工作:
navigator.geolocation.getCurrentPosition(successCallback, errorCallback, {maximumAge:60000, timeout: 2000});
这应该防止实际调用getCurrentPosition函数,如果你在60秒内调用它,但它忽略了这一点(然而,这可能是因为我实际上刷新了我的页面来触发第二次调用,不确定这是否持久跨调用)
顺便说一句,即使谷歌的例子失败在这些浏览器上,这让我相信这确实是浏览器的bug,尝试一下,在Safari中加载两次,第二次就不会工作了。
如果有人找到了解决方案,请告诉我:-)
欢呼。
我有一个部分的答案,但可惜不是一个完整的答案。
首先,要意识到getCurrentPosition的默认超时是无限的(!)。这意味着如果getCurrentPosition挂在后端某个位置,则永远不会调用错误处理程序。
为了确保你得到一个超时,添加可选的第三个参数到你对getCurrentPosition的调用,例如,如果你想让用户等待不超过10秒,然后给他们一个线索发生了什么,使用:
navigator.geolocation.getCurrentPosition(successCallback,errorCallback,{timeout:10000});
其次,我在不同的环境中经历了非常不同的可靠性。在家里,我在一两秒钟内就会收到回复,尽管准确率很低。
然而,在工作中,我经历了相当奇怪的行为变化:地理定位在一些电脑上一直有效(当然IE除外),另一些只能在chrome和safari上工作,但不能在firefox上工作(壁虎问题?),另一些只工作了一次,然后就失败了——这种模式每小时都在变化,每天都在变化。有时你有一台“幸运”的电脑,有时没有。也许满月时宰山羊会有帮助?
我还不能理解这一点,但我怀疑后端基础设施比各种推动这一功能的书籍和网站上宣传的更不平衡。如果您希望错误处理程序正常工作,我真的希望他们能更直接地说明这个特性是多么不可靠,以及超时设置是多么重要。
今天我一直在试着教学生这些东西,遇到了一个尴尬的情况,我自己的电脑(在投影仪和几个大屏幕上)无声地失败了,而大约80%的学生几乎立即得到了结果(使用完全相同的无线网络)。当我的学生也犯拼写错误和其他错误时,当我自己的电脑也出现故障时,解决这些问题是非常困难的。
你不会得到一个错误消息,因为默认情况下它没有超时(至少我认为)。我用firefox也遇到过同样的问题,只是对我来说,firefox总是超时。您可以像这样自己设置一个超时。
我的功能在chrome中工作得很好,但我每次在firefox中都会超时。
navigator.geolocation.getCurrentPosition(
function(position) {
//do succes handling
},
function errorCallback(error) {
//do error handling
},
{
timeout:5000
}
);
我建议你仔细观察你的错误。一切都被期待。为每件事都准备一个备份计划。我使用一些默认值或值从我的数据库自己的情况下谷歌地理位置和导航地理位置失败。
这是我解决这个问题的hack方法,至少它在所有当前的浏览器中都有效(在Windows上,我没有Mac):
if (navigator.geolocation) {
var location_timeout = setTimeout("geolocFail()", 10000);
navigator.geolocation.getCurrentPosition(function(position) {
clearTimeout(location_timeout);
var lat = position.coords.latitude;
var lng = position.coords.longitude;
geocodeLatLng(lat, lng);
}, function(error) {
clearTimeout(location_timeout);
geolocFail();
});
} else {
// Fallback for no geolocation
geolocFail();
}
如果有人点击“关闭”或选择“不”或在Firefox上选择“永不共享”选项,这也会起作用。
很笨拙,但很有效。
以下是我的解决方案,感谢一个闭包:
function geoloc(success, fail){
var is_echo = false;
if(navigator && navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(pos) {
if (is_echo){ return; }
is_echo = true;
success(pos.coords.latitude,pos.coords.longitude);
},
function() {
if (is_echo){ return; }
is_echo = true;
fail();
}
);
} else {
fail();
}
}
function success(lat, lng){
alert(lat + " , " + lng);
}
function fail(){
alert("failed");
}
geoloc(success, fail);
我也遇到了同样的情况。我尝试了超时解决方案,但不可靠。我发现如果你只调用它两次,位置就会正确刷新
function getLocation(callback)
{
if(navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(function(position)
{
navigator.geolocation.getCurrentPosition(callback, function(){},{maximumAge:0, timeout:10000});
},function(){}, {maximumAge:0, timeout:10000});
}
return true;
}
这当然是有点慢,但我没有给我错误的位置一次。我有它击中超时几次,没有返回任何东西,但除此之外,它工作得很好。我知道这仍然有点老套,我期待有人找到真正的解决方案。
或者,如果你想确保它会一直尝试,直到你想放弃,你可以试试这样的方法。
//example
$(document).ready(function(){
getLocation(function(position){
//do something cool with position
console.log(position);
});
});
var GPSTimeout = 10; //init global var NOTE: I noticed that 10 gives me the quickest result but play around with this number to your own liking
//function to be called where you want the location with the callback(position)
function getLocation(callback)
{
if(navigator.geolocation)
{
var clickedTime = (new Date()).getTime(); //get the current time
GPSTimeout = 10; //reset the timeout just in case you call it more then once
ensurePosition(callback, clickedTime); //call recursive function to get position
}
return true;
}
//recursive position function
function ensurePosition(callback, timestamp)
{
if(GPSTimeout < 6000)//set at what point you want to just give up
{
//call the geolocation function
navigator.geolocation.getCurrentPosition(
function(position) //on success
{
//if the timestamp that is returned minus the time that was set when called is greater then 0 the position is up to date
if(position.timestamp - timestamp >= 0)
{
GPSTimeout = 10; //reset timeout just in case
callback(position); //call the callback function you created
}
else //the gps that was returned is not current and needs to be refreshed
{
GPSTimeout += GPSTimeout; //increase the timeout by itself n*2
ensurePosition(callback, timestamp); //call itself to refresh
}
},
function() //error: gps failed so we will try again
{
GPSTimeout += GPSTimeout; //increase the timeout by itself n*2
ensurePosition(callback, timestamp);//call itself to try again
},
{maximumAge:0, timeout:GPSTimeout}
)
}
}
我可能在这里有一些打字和拼写错误,但我希望你能明白。如果有人有问题或者找到更好的建议,请告诉我。
我终于找到了一个工作版本的firefox, chrome和默认导航器在android(仅4.2测试):
function getGeoLocation() {
var options = null;
if (navigator.geolocation) {
if (browserChrome) //set this var looking for Chrome un user-agent header
options={enableHighAccuracy: false, maximumAge: 15000, timeout: 30000};
else
options={maximumAge:Infinity, timeout:0};
navigator.geolocation.getCurrentPosition(getGeoLocationCallback,
getGeoLocationErrorCallback,
options);
}
}
这已经是一个老问题了,但所有的答案都不能解决我的问题,所以让我们加上我最终找到的那个。它闻起来像一种hack(它确实是一种),但在我的情况下总是有效。对你的处境也抱有希望。
//Dummy one, which will result in a working next statement.
navigator.geolocation.getCurrentPosition(function () {}, function () {}, {});
//The working next statement.
navigator.geolocation.getCurrentPosition(function (position) {
//Your code here
}, function (e) {
//Your error handling here
}, {
enableHighAccuracy: true
});
我在Mozilla遇到了这个问题。所有时间:错误:未知错误获取位置。
现在我使用47 Mozilla。我什么方法都试过了,但总是遇到这个问题。但是后来我在我的地址栏打开about:config,进入geo.wifi.ui,并将其值更改为“https://location.services.mozilla.com/v1/geolocate?key=test”。作品!
如果你有位置获取超时错误,尝试增加超时值:
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
navigator.geolocation.getCurrentPosition(success, error, options);
@brennanyoung的回答很好,但如果你想知道在失败的情况下该怎么做,你可以使用IP地理定位API,如https://ipinfo.io(这是我的服务)。这里有一个例子:
function do_something(coords) {
// Do something with the coords here
// eg. show the user on a map, or customize
// the site contents somehow
}
navigator.geolocation.getCurrentPosition(function(position) {
do_something(position.coords);
},
function(failure) {
$.getJSON('https://ipinfo.io/geo', function(response) {
var loc = response.loc.split(',');
var coords = {
latitude: loc[0],
longitude: loc[1]
};
do_something(coords);
});
};
});
详情见https://ipinfo.io/developers/replacing-getcurrentposition。
传递给geolocation . getcurrentposition()的第二个参数是要处理任何地理位置错误的函数。错误处理函数本身接收一个PositionError对象,其中包含关于地理定位尝试失败原因的详细信息。我建议输出错误到控制台,如果你有任何问题:
var positionOptions = { timeout: 10000 };
navigator.geolocation.getCurrentPosition(updateLocation, errorHandler, positionOptions);
function updateLocation(position) {
// The geolocation succeeded, and the position is available
}
function errorHandler(positionError) {
if (window.console) {
console.log(positionError);
}
}
Doing this in my code revealed the message "Network location provider at 'https://www.googleapis.com/' : Returned error code 400". Turns out Google Chrome uses the Google APIs to get a location on devices that don't have GPS built in (for example, most desktop computers). Google returns an approximate latitude/longitude based on the user's IP address. However, in developer builds of Chrome (such as Chromium on Ubuntu) there is no API access key included in the browser build. This causes the API request to fail silently. See Chromium Issue 179686: Geolocation giving 403 error for details.
我发现,这种方法行不通
navigator.geolocation.getCurrentPosition(function() {...}, function(err) {...}, {});
But
这种方法非常有效
function storeCoordinates(position) {
console.log(position.coords.latitude, position.coords.longitude);
}
function errorHandler() {...}
navigator.geolocation.getCurrentPosition(storeCoordinates, errorHandler, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });
在我们的例子中,它总是第一次工作,但重新运行函数3-4次以上,它就失败了。
简单的解决方法:将其值存储在LocalStorage中。
之前:
navigator.geolocation.getCurrentPosition((position) => {
let val = results[0].address_components[2].long_name;
doSthWithVal(val);
}, (error) => { });
后:
if(localStorage.getItem('getCurrentPosition') !== null) {
doSthWithVal(localStorage.getItem('getCurrentPosition'));
}
else {
navigator.geolocation.getCurrentPosition((position) => {
let val = results[0].address_components[2].long_name;
localStorage.setItem('getCurrentPosition',val);
doSthWithVal(val);
}, (error) => { });
}
截至2020年年中,这里的答案都没有提供任何解释,只是黑客攻击或猜测。
正如@Coderer在我之前指出的,安全上下文(https)是今天需要的,所以在越来越多的设备上,地理定位在普通http下根本不起作用:
安全上下文
此特性仅在安全上下文中(HTTPS)以及部分或所有支持的浏览器中可用。
getCurrentPosition()(和watchPosition()更适合这里)的第三个参数是PositionOptions对象,由以下属性组成:
enableHighAccurancy (default false): if set to true, response is slower and more accurate. If you got timeout errors, keep this to false. If the accurancy is low, set it to true. In my tests the accurancy varies and on some devices it has no effect. On other devices setting true may cause surprisingly quick battery depletion.
timeout (default infinity): milliseconds before the API gives up and calls the error handler (the second parameter). Today most mobile devices with geolocation enabled and permission granted for the browser/page get the value with reasonable accurancy within a second. When the geolocation service is not available, alternative method like geo IP may be used, the delay can be many seconds and the precision usually ranges from questionable to useless.
maximumAge (default 0): milliseconds when cached value is valid, the device may decide to use valid cached data instead of sensor measure. I usually set this to non-zero values with slowly moving devices (like walking with mobile phone). On static devices, Infinity can be set to avoid consequent reading errors.
正如@YoLoCo在我之前指出的那样,getCurrentPosition()和watchPosition()会干扰,我在2020年确认了他的结果。通常,使用watchPosition代替getCurrentPosition周期性调用。