navigator.geolocation.getCurrentPosition有时候工作有时不会

时间:2010-08-03 14:37:40

标签: javascript jquery geolocation

所以我使用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

基本上这里发生的是我们获得当前位置,如果获得,两个“水印”被放置在两个字段中,表示“当前位置”,两个隐藏字段是以lat-long数据作为它们的值创建的(它们“一开始就删除了,所以每次都不会重复。”还有两个按钮,它们具有与之相关的点击功能,可以执行相同的操作。 不幸的是,每三次左右,它都有效。 这有什么问题???

25 个答案:

答案 0 :(得分:321)

我一直有完全相同的问题,并且几乎没有在网上找到有关它的信息。书中没有任何东西。最后,我在stackoverflow上找到了这个清醒的查询,并且(哈!)这是我在这里设置帐户所需的最终动力。

我有一个部分答案,但唉不完整。

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

为确保您获得超时,请将可选的第三个参数添加到对getCurrentPosition的调用中,例如,如果您希望用户在给他们了解发生的情况之前等待不超过10秒,请使用:

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

其次,我在不同的环境中经历了截然不同的可靠性。在家里,我会在一两秒内得到一个回调,虽然准确性很差。

然而,在工作中,我遇到了很奇怪的行为变化:地理位置一直在某些计算机上工作(当然,IE除外),其他只能用于chrome和safari而不是firefox(gecko问题?),其他工作一次然后失败 - 模式从一小时变为一小时,从一天到一天。有时候你有一台“幸运”的电脑,有时却没有。也许在满月时屠宰山羊会有帮助吗?

我无法理解这一点,但我怀疑后端基础设施比推广此功能的各种书籍和网站中的广告更不平衡。我真的希望他们能够更直接地了解这个功能的含义,以及超时设置的重要性,如果你希望错误处理程序正常工作

我今天一直在努力向学生传授这些东西,并且在我自己的计算机(在投影仪和几个大屏幕上)默默地失败的情况下出现了令人尴尬的情况,而大约80%的学生几乎立即得到了结果(使用完全相同的无线网络)。当我的学生也在制作拼写错误和其他失误时,以及当我自己的电脑也失败时,很难解决这些问题。

无论如何,我希望这可以帮助你们中的一些人。谢谢你的理智检查!

答案 1 :(得分:63)

这是我解决这个问题的黑客方式,至少它适用于所有当前的浏览器(在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上选择“永不共享”选项,这也会有效。

笨拙,但它确实有效。

答案 2 :(得分:37)

每次都适合我:

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

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

答案 3 :(得分: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's examples在这些浏览器上都失败了,这让我相信这确实是浏览器错误,尝试一下,在Safari中加载两次,第二次就无法运行。

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

干杯。

答案 4 :(得分:12)

这已经是一个老问题,但所有答案都没有解决我的问题,所以让我们添加一个我最终找到的答案。它闻起来像一个黑客(它是一个),但总是在我的情况下工作。也希望你的情况。

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

答案 5 :(得分:6)

您没有收到错误消息,因为它默认没有超时(至少我认为)。我和firefox有同样的问题只有我firefox总是给出一个超时。您可以像这样设置超时。

我已将最大年龄设置为Infinity,以确保不会出现问题。我的函数在chrome中工作得很好,但我每次都在firefox中获得超时。

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

我建议您仔细观察您的错误。应有尽有。为所有事情制定备份计划。如果Google地理位置和导航地理位置都失败,我会自己使用数据库中的一些默认值或值。

答案 6 :(得分:5)

我在2017年仍然得到了不稳定的结果,我有一个理论:the API documentation说现在只能在安全的上下文中使用#34;即通过HTTPS。我在开发环境中遇到问题(本地主机上的http),我相信这就是原因。

答案 7 :(得分: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;
}

这当然有点慢,但我没有让它一次给我错误的位置。我已经让它超时了几次并且没有返回任何东西,但其他它然后效果很好。我知道这仍然有点hacky,我期待有人找到真正的解决方案。

或者,如果你想确保它会继续尝试,直到你想放弃,你可以尝试这样的事情。

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

我可能在这里有一些类型和一些拼写错误,但我希望你能得到这个想法。如果有人有疑问或者有人找到更好的东西,请告诉我。

答案 8 :(得分:4)

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

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

答案 9 :(得分:3)

对于在iPhone应用程序上工作的任何人......

如果您的代码在iOS 9+上的UIWebView中运行,那么您必须在应用程序的plist中设置getCurrentPosition

如果您没有设置它,那么sed -n "/pattern/,$p" < input.inp > output.out 将永远不会回拨,并且永远不会提示用户。

答案 10 :(得分: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);
        });  
    };
});

有关详细信息,请参阅http://ipinfo.io/developers/replacing-navigator-geolocation-getcurrentposition

答案 11 :(得分:2)

我终于找到了firefox,chrome&amp;的工作版本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);
        }
    }

答案 12 :(得分:2)

我一直有类似的问题,并且一直在研究浏览器对getCurrentPosition调用频率的限制。我似乎经常可以获得一个位置,但如果我立即刷新页面它会超时。如果我等一下,我通常可以再次获得一个位置。这通常发生在FF上。在Chrome和Safari中,我还没有注意到getCurrentPosition超时。只是一个想法...

虽然我找不到任何支持这一点的文档,但经过多次测试后我才得出结论。也许其他人有关于此的一些信息?

答案 13 :(得分:2)

我发现,这种方式不起作用

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

答案 14 :(得分: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”。事实证明,谷歌Chrome使用Google API在没有内置GPS的设备上获取位置(例如,大多数台式计算机)。 Google会根据用户的IP地址返回大致的纬度/经度。 但是,在Chrome的开发人员版本中(例如Ubuntu上的Chromium),浏览器版本中不包含API访问密钥。这会导致API请求以静默方式失败。有关详细信息,请参阅Chromium Issue 179686: Geolocation giving 403 error

答案 15 :(得分: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) => { });
}

答案 16 :(得分:1)

我会在此发布此内容,以防对任何人有用......

在iOS Safari上,如果我有一个活动的navigator.geolocation.getCurrentPosition函数,对navigator.geolocation.watchPosition的调用将会超时。

使用此处所述的watchPosition正确启动和停止clearWatch(),工作:https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition

答案 17 :(得分:1)

截至2020年中,这里的答案都没有提供任何解释,只是黑客或猜测。

正如@Coderer在我面前指出的那样,今天需要安全上下文(https),因此在越来越多的设备上使用纯http:根本无法进行地理位置定位。

安全上下文 此功能仅在某些或所有支持的浏览器中的安全上下文(HTTPS)中可用。

getCurrentPosition()的第三个参数(此处更合适的是watchPosition())是PositionOptions对象,由以下属性组成:

  • enableHighAccurancy(默认为false):如果设置为true,则响应会更慢且更准确。如果发生超时错误,请将其保留为false。如果精度较低,则将其设置为true。在我的测试中,延迟为1秒,精度为1-2米,在UMAX平板电脑上,真假之间没有区别。如果设置为false,我也在5米振动的旧版iPhone上进行了测试。您还可以在GeolocationCoordinates.accurancy属性中测量准确性并动态决定。
  • timeout(默认无穷大):API放弃并调用错误处理程序(第二个参数)之前的毫秒数。如今,5分(5000)是合理的,在某些情况下10分可以理解。如果您在没有地理位置传感器数据的情况下想要拥有计划B,则很有用。
  • maximumAge(默认值为0):缓存值有效时的毫秒数,设备可能会决定使用有效的缓存数据而不是传感器量度。在静态位置将此值设置为Infinity,否则保持为0。

正如@YoLoCo在我面前指出的那样,getCurrentPosition()watchPosition()会干扰我,并在2020年确认他的结果。通常,请使用watchPosition而不是getCurrentPosition定期调用。

答案 18 :(得分:1)

getCurrentPosition失败时,使用IP地址地理位置服务作为回退方法可能是个好主意。例如,使用我们的api https://ip-api.io

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

答案 19 :(得分: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);

答案 20 :(得分:0)

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

除了必须使用watchPosition()而不是getCurrentPosition()之外,我还发现我需要将来自document.ready()的调用移到头部。

答案 21 :(得分:0)

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

答案 22 :(得分:0)

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

答案 23 :(得分:0)

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

答案 24 :(得分:0)

我最近自己注意到了这个问题,而且我不确定它是怎么发生的,但有时会出现firefox卡在缓存中加载的东西上。清除缓存并重新启动Firefox后,它似乎再次运行。