重试地理定位请求而不刷新浏览器

Shi*_* Cr 2 javascript geolocation

我对 Geolocation api 有一个具体问题。这是我的场景:

\n\n
    \n
  1. 用户登陆的页面(在 Chrome - Android 中)禁用了 GPS 位置。
  2. \n
  3. 页面上有一个按钮,按钮的onClick触发Geolocation.getCurrentPosition
  4. \n
  5. Geolocation 进入错误回调,并显示错误消息 \xe2\x80\x9cUser returned Geolocation\xe2\x80\x9d
  6. \n
  7. 用户进入Android设置(主要在通知抽屉中)并打开位置
  8. \n
  9. 用户再次点击按钮(此时位置可用)即可获取坐标
  10. \n
  11. 但是,Geolocation api 仍然会抛出错误 \xe2\x80\x9cUser returned Geolocation\xe2\x80\x9d
  12. \n
\n\n

\xe2\x80\x94

\n\n
    \n
  1. 此时,只有用户刷新页面并按下按钮,地理定位请求才会起作用(注意:位置仍然启用)
  2. \n
\n\n

有没有办法在不刷新浏览器的情况下完成这项工作?

\n\n

这是 jsbin 链接: https: //output.jsbin.com/pihenud

\n

Shi*_* Cr 5

最后,我能够使用 iFrame hack 解决这个问题。

这是解决方案:

动态创建一个 iFrame 并在其中调用,而不是在主窗口中请求权限geolocation.getCurrentPosition。现在,我们可以使用window.postMessage将位置数据传递到父浏览器窗口。

当我们必须再次重试地理定位请求时,我们只需要重新加载 iframe——这将具有新的站点设置。

如果有人想尝试的话,这是 iframe 代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Namshi Geolocation</title>
</head>
<body>
  <script type="text/javascript">
    var sendMessage = function(result){
      window.postMessage(JSON.stringify(result), window.location.origin);
    };

    var triggerGeolocationRequest = function(){
      var options = {
        enableHighAccuracy: true,
        timeout: 10000,
        maximumAge: 0
      };

      var result;

      if(window.navigator.geolocation){
        window.navigator.geolocation.getCurrentPosition(function(position){
          var result = {
            type: 'success',
            data: {lat: position.coords.latitude, lng: position.coords.longitude}
          };
          sendMessage(result);
        }, function(err){
          var result = {
            type: 'error',
            data: { message: err.message, code: err.code }
          };
          sendMessage(result);
        }, options)
      } else {
        result = {
          type: 'error',
          data: { message: 'No Geolocation API' }
        };
        sendMessage(result);
      }
    };
    window.addEventListener('load', triggerGeolocationRequest);
  </script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

在您的应用程序代码中,您可以使用一个实用程序来注入 iFrame。请看下面的代码:

utils.getCurrentPosition = function(){
  return new Promise(function(resolve, reject){
    var ifr = document.createElement('iframe');
    ifr.style.opacity = '0';
    ifr.style.pointerEvents = 'none';
    ifr.src = location.origin + '/geo.html'; // the previous html code.

    document.body.appendChild(ifr);

    ifr.contentWindow.addEventListener('message', function(message){
      message = JSON.parse(message.data);
      if(message.type === 'success'){
        resolve(message.data);
      } else {
        reject(message.data);
      }
      document.body.removeChild(ifr);
    });
  });
};
Run Code Online (Sandbox Code Playgroud)