navigator.geolocation.getCurrentPosition有时有效,有时却无效


220

因此,我使用了navigator.geolocation.getCurrentPosition jammy,使用了相当简单的JS。

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

基本上,这里发生的是我们得到当前位置,如果获得了当前位置,则将两个“水印”放置在两个表示“当前位置”的字段中,并使用经纬度数据作为其值来创建两个隐藏字段(将它们删除)一开始就不会重复)。还有两个按钮具有绑定在一起的单击功能,它们执行相同的操作。不幸的是,它每三分钟左右就可以工作。这是什么问题???


也许在使用功能之前先定义它们。
tcooc 2010年

4
@digitalFresh,这没关系,因为JS解析器会在代码开始执行之前查找这些声明
antimatter15

是否可能在其中使用jQuery引起问题?
theassociatedweb

1
当您说有时它不起作用时,您到底是什么意思?该noLocation函数被调用了吗?如果是这样,你可以在添加error参数noLocation(),然后error.codeerror.message可以帮助您调试。它还可能有助于我们了解您使用的是哪种浏览器,以及在不同的浏览器中是否遇到相同的问题。
npdoty

我的意思是有时它给我带来了延迟,有时却没有。当它不起作用时,它甚至不会抛出“找不到位置”消息,因此noLocation位也不会触发。
theassociatedweb 2010年

Answers:


342

我遇到了完全相同的问题,并且几乎没有关于它的在线信息。书中什么都没有。最终,我发现了这个关于stackoverflow的清醒查询,这是我在这里设置帐户所需的最终动力。

我有一个部分答案,可惜不是一个完整的答案。

首先,认识到getCurrentPosition 的默认超时无限的(!)。这意味着如果getCurrentPosition挂在后端某处,将永远不会调用您的错误处理程序。

为了确保超时,请在对getCurrentPosition的调用中添加可选的第三个参数,例如,如果希望用户等待不超过10秒的时间来告诉他们正在发生的事情,请使用:

navigator.geolocation.getCurrentPosition(successCallback,errorCallback,{timeout:10000});

其次,我在不同的情况下经历了完全不同的可靠性。在家里,尽管准确性很差,但我在一两秒钟之内收到了回调。

但是,在工作中,我会遇到非常奇怪的行为变化:地理位置始终在某些计算机上工作(当然,IE除外),其他人只能在chrome和safari中工作,而不能在Firefox中工作(壁虎问题?),其他人工作一次,然后再工作失败-模式每天都在每小时之间变化。有时您有一台“幸运”计算机,有时却没有。也许在满月时宰杀山羊会有所帮助?

我无法理解这一点,但是我怀疑后端基础设施比推动该功能的各种gung-ho书和网站所宣传的更加不平衡如果您希望错误处理程序正常工作,我真的希望他们对这个功能的实用性以及超时设置的重要性有更多的了解。

我今天一直在尝试向学生讲这些东西,而令人尴尬的情况是我自己的计算机(在投影仪和几个大屏幕上)无声地出现故障,而大约80%的学生几乎立即获得了结果(使用完全相同的无线网络)。当我的学生们还在打错字和其他失误,并且我自己的电脑也出现故障时,解决这些问题非常困难。

无论如何,我希望这对你们中的一些人有所帮助。感谢您的健全性检查!


5
好详细的信息,谢谢!我看到了同样的问题,但仅在Firefox 3.6.13上。Chrome似乎非常可靠。
菲利佩·利马

此处相同,并且maximumAge参数似乎也不可靠。感谢您的帖子。
理查德

1
不错,我遇到了同样的问题(在运行Android 4.0.3Samsung Galaxy Tab 10.1上),一旦我使用了上面的超时参数,就可以解决该问题。
mlo55

9
重要的是要了解timeout选项getCurrentPosition()实际上是时间。允许或拒绝地理位置请求的时间不是用户,而是授予许可后允许网络返回位置所花费的时间。如果用户不回答地理位置请求,则将永远不会调用错误处理程序。因此,您需要第二次超时,例如@ xiaohouzi79答案。
弗朗索瓦2014年

2
在满月时宰杀山羊会有所帮助吗?LOL
阿西KT

66

这是我解决这个问题的一种方法,至少在所有当前的浏览器中都可以使用(在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();
}

如果有人在Fi​​refox上单击关闭或不选择或选择从不共享选项,这也将起作用。

笨拙,但有效。


1
+1但是您缺少geolocFail();错误处理程序和getcodeLatLng();地理编码器。
kaiser 2012年

甜蜜的-如果有人选择不共享位置,则计时器的工作效果非常好。用户这样做时,某些浏览器不能很好地播放。在我的Store Locator Plus WP插件上,此计时器解决方法非常有效!
兰斯·克利夫兰

2
@sajith-不知道此解决方案是否已在最近的FF浏览器中过时。在我提供解决方案时,它就起作用了,因为我正在使用的站点需要它。你测试了吗
2012年

抱歉,它起作用了。但是我找不到使它起作用的原因。关闭并重新打开FF后它的工作
原理

1
您不应该在字符串中使用函数。邪恶的评价毫不留情地在那里工作。setTimeout(“ geolocFail()”,10000);
atilkan

42

每次都对我有用:

navigator.geolocation.getCurrentPosition(getCoor, errorCoor, {maximumAge:60000, timeout:5000, enableHighAccuracy:true});

虽然不是很准确。有趣的是,如果我在同一台设备上运行它,它将使我离开大约100米(每次),但是如果我去Google的地图,它将准确地找到我的位置。因此,尽管我认为enableHighAccuracy:true可以帮助其始终如一地工作,但似乎并没有使其更加准确...


这已阻止Firefox拒绝请求并发回超时对象。
托尼2012年

我附属的手机信号塔在100米外。因此,它返回的是手机信号塔的位置,而不是我的手机。也许更加准确,如果我在外面为GPS一命呜呼
K'shin GENDRON

9
因为您将maximumAge参数设置为60秒,所以它会使您离开数米。因此,将您的位置设置为60秒前的位置。将maximumAge设置为10秒或更短(maximumAge:10000),然后重试。
罗伯·史密斯

我在返回一个Observable的Angular Resolver中使用了这个getCurrentPosition。解析器仅间歇完成。添加以下选项:{maximumAge:60000,timeout:5000,enableHighAccuracy:true}使其每次都能正常工作!!!
Moutono

17

这已经是一个老问题了,但是所有答案都不能解决我的问题,所以让我们添加一下我终于找到的问题。它闻起来像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
});

3
那是最骇人听闻的骇客,我不知道您怎么想尝试它,但这解决了我的问题。谢谢!
Brett Gregson,

在某些情况下,我本人已使用过此功能。根据我的经验,第二次尝试总是效果更好
Nico Westerdale

13

同样的人,这在Chrome(稳定版,开发者版和金丝雀版)中完美运行,而在FF和Safari中则完美。它也可以在我的iPhone和iPad(Safari!)上完美运行。这可能是由于此功能相对较新(即它是一个错误)。我现在花了将近一个星期的时间,但我无法在这些浏览器上使用它

这是我发现的:

第一次调用getCurrentPosition时,它可以完美工作。任何后续调用都不会返回,即不会触发successCallback或errorCallback函数。我在通话中添加了一些头寸选项以证明我的观点:

 navigator.geolocation.getCurrentPosition(successCallback, errorCallback,  {timeout: 10000});

并且每次(第一次成功呼叫后)都会超时。我以为可以用maximumAge修复它,但是似乎也不能正常工作:

navigator.geolocation.getCurrentPosition(successCallback, errorCallback,  {maximumAge:60000, timeout: 2000});

如果您在60秒内调用getCurrentPosition函数,这应该可以防止实际调用它,但是它会忽略此操作(但是,这可能是由于我实际上刷新页面以触发第二次调用,不确定这是否是持久的跨调用)

顺便说一句,即使是google的示例在这些浏览器上都失败了,这使我相信这确实是浏览器的错误,请尝试一下,在Safari中加载两次,第二次将无法使用。

如果有人找到解决方案,请告诉我:-)

干杯。


我有与您一样的确切问题,它适用于第一个电话,但不适用于下一个电话,如果有人找到解决方案,我将非常感兴趣... @ xiaohouzi79您的解决​​方案每次(除第一个解决方案外)都在geolocFail( )
阿德里亚诺·里佐

8

您不会收到错误消息,因为默认情况下它没有超时(至少我认为)。我对firefox也有同样的问题,仅对我来说firefox总是超时。您可以这样设置自己的超时时间。

我的功能在chrome中效果很好,但是每次在Firefox中都会超时。

    navigator.geolocation.getCurrentPosition(
        function(position) {
            //do succes handling
        },
        function errorCallback(error) {
            //do error handling
        },
        {
            timeout:5000
        }
    );

我建议仔细观​​察您的错误。期望一切。有一切的备份计划。我自己使用一些默认值或我自己数据库中的值,以防google地理位置和导航器地理位置都失败。


7
只是一个FYI,maximumAge是指缓存中位置数据的使用期限,将其设置为infinity可以确保您获得缓存版本。将其设置为0会强制设备检索位置。
波尔科

拒绝投票,是因为maximumAge:Infinity会像上面指出的那样使您烦恼,这意味着强制使用缓存的值。
n13

7

我在2017年的结果仍然参差不齐,而且我有一个理论:API文档说,该调用现在只能在“安全上下文”中使用,即通过HTTPS。我在开发环境(本地主机上的http)上无法获得结果,我相信这就是原因。


嗯,很有趣。即使在2020年,localhost上的HTTPS仍然存在问题!
NitroStoutPlz


5

这是我的解决方案,感谢闭包:

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

这为我工作在反应母语 navigator && navigator.geolocation
阿希什·辛格拉瓦特

5

所以我遇到了同样的事情。我尝试了超时解决方案,该解决方案有效但不可靠。我发现,如果您只打了两次电话,位置就会正确刷新

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

我可能在这里遇到一些打字错误和一些拼写错误,但希望您能明白。让我知道有人是否有疑问或有人发现更好的东西。


4

对于使用iPhone应用程序的任何人...

如果您的代码在iOS 9+的UIWebView中运行,则必须NSLocationWhenInUseUsageDescription在应用程序的plist中进行设置。

如果您未设置,则getCurrentPosition永远不会回叫,也永远不会提示用户。


3

我发现这种方式行不通

navigator.geolocation.getCurrentPosition(function() {...}, function(err) {...}, {});

这样完美

function storeCoordinates(position) {
    console.log(position.coords.latitude, position.coords.longitude);
}    

function errorHandler() {...}

navigator.geolocation.getCurrentPosition(storeCoordinates, errorHandler, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });

4
两者有什么区别?
Pardeep Jain

匿名函数vs命名为1
1nstinct

确实有很大的差异。谢谢你,这也不工作
withoutOne

3

@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


这是针对此问题的更正链接:ipinfo.io/developers/replacing-getcurrentposition
peater

5
可怕。在美国和加拿大时,准确度与实际位置相距5-7英里,而在俄罗斯某处则相距100英里。
ekashking

1
对于很多应用程序来说,这很好-比不知道位置在哪里要好得多。
Ben Dowling

这在任何地方都行不通。每个请求将经度和纬度视为错误的请求
没有一个

你是什​​么意思?你有一些例子吗?
本道林

2

我遇到过类似的问题,并一直在研究浏览器是否有限制getCurrentPosition调用频率的可能性。看来我经常可以找到一个位置,但是如果我立即刷新页面,它将超时。如果我稍等一下,通常可以再次找到一个位置。FF通常会发生这种情况。在Chrome和Safari中,我尚未注意到getCurrentPosition超时。只是一个想法...

尽管我找不到任何文档来支持此操作,但这是经过大量测试后得出的结论。也许其他人对此有一些了解?


那是个很好的观点。我的超时/失败似乎主要发生在我进行测试并反复查询地理位置数据时。我很想知道这是错误的结果,还是您所建议的设计结果。
Jamie

我还没有看到浏览器限制对定位服务的呼叫数量的情况。您多久查询一次?
Nico Westerdale

2

我终于在android中找到了适用于Firefox,Chrome和默认导航器的工作版本(仅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);
        }
    }

2

传递给第二个参数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);
  }
}

在我的代码中执行此操作将显示消息“位于' https://www.googleapis.com/的网络位置提供商:返回的错误代码400”。事实证明,谷歌浏览器使用Google API在未内置GPS的设备(例如,大多数台式计算机)上获取位置。Google会根据用户的IP地址返回近似的纬度/经度。但是,在Chrome开发人员版本(例如Ubuntu上的Chromium)中,浏览器版本中没有API访问密钥。这将导致API请求静默失败。有关详细信息,请参见Chromium问题179686:地理定位给出403错误


1

我在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);

1

getCurrentPosition失败时,最好使用IP地址地理位置服务作为后备方法。例如我们的api https://ip-api.io

$.getJSON("http://ip-api.io/json/",
    function(result) {
        console.log(result);
    });

1

在我们的例子中,它总是第一次工作,但是重新运行该功能超过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) => { });
}

0

我本人最近注意到了这个问题,我不确定它是怎么发生的,但是有时Firefox会卡在缓存中加载的内容上。清除缓存并重新启动firefox之后,它似乎又可以工作了。


0

该库为地理位置调用添加了desiresAccuracy和maxWait选项,这意味着它将继续尝试获取位置,直到精度在指定范围内。


0

感谢大家的投入,这对我有所帮助。

除了不得不使用watchPosition()而不是getCurrentPosition()之外,我还发现我需要将调用从document.ready()内部移到头部。


0

使用Firefox的响应式设计模式时,这发生在我身上。已提交错误报告。目前,仅在使用Geolocation API时不要使用自适应设计模式。


0

可能对某些人有所帮助,但在Android上我也遇到了同样的问题,但是我通过setTimeout 内部 使用弄清了它, document.ready 因此对我有用。第二,您必须增加超时时间,以防万一用户在几秒钟后允许其位置,那么我将其保留为60000毫秒(1分钟),如果用户在1分钟内单击允许按钮,则可以调用我的成功功能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.