web-dev-qa-db-ja.com

navigator.geolocation.getCurrentPositionが機能しないことがある

だから私は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

基本的にここで起こっているのは、現在位置を取得することです。取得されると、2つの "透かし"が "現在位置"と言う2つのフィールドに配置され初めにそれらが毎回複製されないように)。同じことをするそれらに結び付けられたクリック機能を持つ2つのボタンもあります。残念なことに、3回ごとに、それは動作します。ここで問題は何ですか?

198

私は正確に同じ問題を抱えていて、それについての情報をオンラインでほとんど見つけていません。本には何もありません。最後に、私はstackoverflowに関するこの率直な質問を見つけました、そして(ハ!)これは私がここでアカウントを設定するために必要な最後の推進力でした。

そして部分的な答えがありますが、残念ながら完全な答えではありません。

まず最初に、getCurrentPositionのdefault timeoutinfinite(!)であることを理解してください。つまり、getCurrentPositionがバックエンドのどこかでハングした場合、エラーハンドラは決して呼び出されることはありませんになります。

確実にタイムアウトを取得するには、getCurrentPositionへの呼び出しにオプションの3番目のパラメータを追加します。たとえば、ユーザーに何が起こっているのかを知る前に10秒以内に待たせる場合は、次のようにします。

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

第二に、私はさまざまな文脈で全く異なる信頼性を経験しました。ここでは自宅で、1秒か2秒以内にコールバックが返されますが、正確さは劣ります。

しかし、仕事では、私はかなり奇妙なふるまいのバリエーションを経験します。ジオロケーションは常に一部のコンピュータで動作し(もちろんIEは除く)、他はクロムとサファリで動作しますがFirefoxでは動作しません。失敗します - そしてパターンは時々刻々と変化します。時にはあなたは「幸運な」コンピュータを持っていますが、そうでないこともあります。おそらく満月にヤギを屠殺することは助けになるでしょうか?

これを推測することはできませんでしたが、この機能を推進しているさまざまなgung-ho関連書籍やWebサイトで、バックエンドインフラストラクチャは宣伝されているものよりも不均一ですと思われます。私は、この機能がどれほどゆるいかについて、もう少しまっすぐになること、そしてエラーハンドラを正しく動作させたいのであれば、タイムアウト設定がどれほど重要であるかになることを本当に望みます。

私は今日このことを学生に教えようとしていました、そして私の自身のコンピューター(プロジェクターといくつかの大きなスクリーン)が静かに失敗していた恥ずかしい状況がありました。まったく同じ無線ネットワーク)。私の学生がタイプミスや他の間違いをしているとき、そして私自身のPCも失敗しているとき、これらの問題を解決することは非常に困難です。

とにかく、私はこれがあなた方の何人かに役立つことを願っています。健全性チェックをありがとう!

321
brennanyoung

これは私がこれを回避している厄介な方法です、少なくともそれは現在のすべてのブラウザで動作します(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で誰かが閉じるをクリックするか、[いいえ]を選択するか、[共有しない]オプションを選択した場合にも機能します。

不格好ですが、うまくいきます。

63
going

これは毎回私のために働きます:

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

非常に正確ではありませんが。面白いのは、同じデバイスでこれを実行すると100メートルほど(毎回)オフになることですが、Googleの地図にアクセスすると正確に自分の位置がわかります。それで私はenableHighAccuracy:trueがそれが首尾一貫して働くのを助けると思うけれども、それがそれをそれ以上正確にするようには思わない...

37
K'shin Gendron

ここでも同じですが、これはChromeでも安定して動作します(安定版、開発版、カナリア版)、FFとSafariではうまくいきません。それは私のiPhoneとiPad(Safari!)でも完璧に動作します。これは、この機能の相対的な新しさが原因である可能性があります(つまり、バグです)。私は今これにほぼ1週間を費やして、私はちょうどそれらがそれらのブラウザで動作するようにすることができません

これが私が見つけたものです:

初めてgetCurrentPositionを呼び出すときは、完璧に機能します。それ以降の呼び出しは決して戻りません。つまり、successCallbackまたはerrorCallback関数は起動されません。私は自分の主張を証明するために私の電話にいくつかの位置オプションを追加しました:

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

そしてそれは毎回タイムアウトします(最初の呼び出し成功後)。 maximumAgeで修正できると思いましたが、うまくいくとは思われません。

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

60秒以内に呼び出しても実際にはgetCurrentPosition関数を呼び出すことはできませんが、これは無視されます(ただし、これは、2番目の呼び出しをトリガーするために実際にページを更新するためです

ところで、 google's examples これらのブラウザでは失敗するので、これは確かにブラウザのバグであると信じ、試して、Safariに2回ロードしても2回目には動作しません。

誰かがこれの解決策を見つけたら、私に知らせてください:-)

乾杯。

13
mvilrokx

これはすでに古い質問ですが、すべての答えで私の問題は解決しませんでしたので、最後に見つけたものを追加しましょう。それはハックのように(そしてそれは一つです)匂いがしますが、私の状況では常に動作します。あなたの状況でも願っています。

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

デフォルトではタイムアウトがないのでエラーメッセージは表示されません(少なくとも私は思います)。私はFirefoxにいつも同じ問題を抱えていますが、Firefoxは常にタイムアウトを出します。このように自分でタイムアウトを設定できます。

これが問題にならないように、最大​​年齢をInfinityに設定しました。私の関数はクロムではうまく動作しますが、私はFirefoxで毎回タイムアウトになります。

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

私はあなたの間違いを注意深く見ることを勧めます。すべてに期待されています。すべてのバックアップ計画を立てます。 Googleの位置情報とナビゲーターの位置情報の両方が失敗した場合に備えて、私は自分自身のデータベースのデフォルト値または値を使用します。

6
Mark Baijens

私は2017年にまだむらのある結果を得ています、そして私は理論を持っています: APIドキュメント は、呼び出しが「安全なコンテキストで」、すなわちHTTPS経由でのみ利用可能になると言います。私は自分の開発環境(http on localhost)で結果が得られないので、これが理由だと思います。

5
Coderer

だから私は同じことに遭遇しました。私はうまくいったが確実ではないタイムアウト解決策を試した。 2回呼び出すだけで場所が正しく更新されることがわかりました

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

私はおそらくここにいくつかのタイプミスといくつかのスペルミスがありますが、私はあなたがアイデアを得ることを願っています。誰かが質問をしているのか、誰かがより良いものを見つけたのであれば教えてください。

5
Drew Calder

これは閉鎖のおかげで私の解決策です:

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

IPhoneアプリで作業している人のために...

コードがiOS 9以降のUIWebViewで実行されている場合は、アプリのplist内にNSLocationWhenInUseUsageDescriptionを設定する必要があります。

設定しなかった場合、getCurrentPositionはコールバックせず、ユーザーにプロンプ​​トを表示しません。

3
bendytree

@ brennanyoungの答えは素晴らしいですが、失敗した場合に何をすべきか疑問に思っている場合は、 https://ipinfo.io (これは私のサービスです)などのIP位置情報APIを使用できます。これが例です:

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 を参照してください。

3
Ben Dowling

私はついに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
surfealokesea

Geolocation.getCurrentPosition() に渡される2番目のパラメータは、ジオロケーションエラーを処理するための関数です。エラーハンドラ関数自体が、位置情報の取得に失敗した理由に関する詳細を含む 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 Chromeは、Google APIを使用して、GPSが組み込まれていないデバイス(たとえば、ほとんどのデスクトップコンピュータ)の場所を特定します。 Googleは、ユーザーのIPアドレスに基づいておおよその緯度/経度を返します。 ただし、、Chromeの開発者向けビルド(Chromium on Ubuntuなど)では、ブラウザビルドにAPIアクセスキーは含まれていません。これにより、API要求は暗黙のうちに失敗します。詳細については、 Chromium Issue 179686:位置情報が403エラーになる を参照してください。

2
thirdender

この方法ではうまくいかないことがわかりました

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 });
2
1nstinct

私は同様の問題を抱えており、ブラウザがgetCurrentPositionを呼び出すことができる頻度に制限がある可能性を調べています。たまに場所を取得できるようですが、すぐにページを更新するとタイムアウトになります。少し待っていれば、たいていはまた場所を見つけることができます。これは通常FFで起こります。 ChromeとSafariでは、getCurrentPositionがタイムアウトするのにはまだ気付いていません。ちょっとした考え...

これを裏付ける文書を見つけることはできませんが、多くのテストを経て私がたどり着いた結論でした。おそらく他の誰かがそれについて何らかの情報を持っていますか?

2
brewster

私はMozillaでこの問題を抱えています。すべての時間:エラー:位置取得中の不明なエラー

今私は47のMozillaを使用しています。私はすべてを試みましたが、いつもこの問題です。 BUTそれから私は開いていますabout:config私のアドレスバーに行ってくださいgeo.wifi.uiそして値を "---"に変更しました https://location.services.mozilla.com/v1/geolocate?key=test "動作します。

Uが位置取得タイムアウトエラーの場合は、タイムアウト値を増やしてみてください。

var options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0       
};
navigator.geolocation.getCurrentPosition(success, error, options);
1
Vasyl Gutnyk

誰にでも役立つように、これをここに投稿します…

IOS Safariでは、アクティブなnavigator.geolocation.getCurrentPosition関数を実行しているとnavigator.geolocation.watchPositionの呼び出しがタイムアウトします。

ここで説明されているようにclearWatch()を使用してwatchPositionを適切に起動および停止することができました。 https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition

1
JoLoCo

getCurrentPositionが失敗した場合は、フォールバック方法としてIPアドレス地理位置情報サービスを使用することをお勧めします。例えば私達のapi https://ip-api.io

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

このライブラリ ジオロケーション呼び出しにdesiredAccuracyオプションとmaxWaitオプションを追加します。つまり、精度が指定された範囲内になるまで位置を取得しようとし続けます。

0
Mike McKay

私たちの場合、それは常に最初に動作しますが、関数を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
David Vielhuber

私は最近自分自身でこの問題に気付きました、そしてそれがどのように起こるのか私にはわかりませんが、それは時々Firefoxがキャッシュにロードされた何かに行き詰まるように見えるでしょう。キャッシュをクリアしてFirefoxを再起動すると、それは再び機能するように見えます。

0
Assimilater

ご意見をいただきありがとうございました。

GetCurrentPosition()の代わりにwatchPosition()を使用しなければならないことに加えて、私はdocument.ready()内からヘッドに呼び出しを移動する必要があることもわかりました。

0
user2217751