`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起 [英] `navigator.geolocation.getCurrentPosition()` hangs on iOS PWA

查看:54
本文介绍了`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个片段:

const getCurrentPosition = () =>
  new Promise<GeolocationPosition>((resolve, reject) => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(resolve, reject, {
        timeout: 5000,
        maximumAge: 2000,
        enableHighAccuracy: true,
      });
    } else {
      reject(new Error('Browser does not support geolocation!'));
    }
  });

我这样称呼:

try {
  const { coords } = await getCurrentPosition();
  // do stuff with coords
}
catch (e){
  // handle the error
}

在 iOS PWA (navigator.standalone) 中执行此代码时,如果我有 Safari 的位置设置 (Settings > Privacy> Location Services > Safari 网站) 设置为:Ask Next TimegetCurrentPosition() 承诺挂起并且不会超时、解决或拒绝.它不会像在 iOS Safari 浏览器中那样提示我输入我的位置

When executing this code in an iOS PWA (navigator.standalone) if I have my location settings for Safari (Settings > Privacy > Location Services > Safari Websites) set to: Ask Next Time, the getCurrentPosition() promise hangs and does not timeout, resolve or reject. It does not prompt me for my location like it does in the iOS Safari browser

如果我将设置更改为 NeverWhile Using the App,那么它会提示我并且工作正常.

If I change the settings to Never or While Using the App, then it prompts me and works fine.

我希望能够处理用户在使用 PWA 时将其设置设置为 Ask Next Time 的场景.

I want to be able to handle the scenario where a user has set their settings to Ask Next Time whilst using a PWA.

推荐答案

一旦一些同事和我想通了,这个问题的解决方案是相当微不足道的:

The solution to this was fairly trivial once some colleagues and I figured it out:

export function getUserPosition(): Promise<GeolocationPosition> {
  const promiseArray = [];

  if (navigator.standalone) {
    promiseArray.push(
      new Promise((resolve, reject) => {
        const wait = setTimeout(() => {
          clearTimeout(wait);
          reject('Location has timed out');
        }, 4000);
      })
    );
  }

  const getCurrentPositionPromise = new Promise((resolve, reject) => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(resolve, reject, {
        timeout: 5000,
        maximumAge: 2000,
        enableHighAccuracy: true,
      });
    } else {
      reject(new Error('Browser does not support geolocation!'));
    }
  });

  promiseArray.push(getCurrentPositionPromise);

  return Promise.race(promiseArray) as Promise<GeolocationPosition>;
}

这是怎么回事?

  1. 我们正在创建一个空的承诺数组
  2. 如果导航器被标识为 standalone,我们将创建一个承诺,在 4 秒后 rejects(该值是任意的,您希望用户使用的最长时间)等待)并将其推送到 promiseArray.
  3. 我们正在创建另一个 promise,它获取用户的位置并将其推送到 promiseArray 中.
  4. 然后我们返回一个从 Promise.race() 的执行返回的承诺.这里的关键是,如果导航器不是 standalonepromiseArray 中将只有一个 promise,因此将按预期工作.如果导航器是独立的,那么 promiseArray 中将有两个 promise,Promise.race() 将拒绝超时,从而拒绝 getUserPosition() 函数.
  1. We're creating an empty promise array
  2. If the navigator is identified as standalone, we're creating a promise that rejects after 4 seconds (this value is arbitrary, the maximum time you want your users to wait) and pushing it to the promiseArray.
  3. We're creating another promise which gets the user's position and pushing that into the promiseArray as well.
  4. We then return a promise that is returned from the execution of Promise.race(). The key here is that there will only be one promise in the promiseArray if the navigator is not standalone, and will therefore work as intended. If the navigator is standalone, then there will be two promises in the promiseArray and the Promise.race() will reject from the timeout, thus rejecting from getUserPosition() function.

这篇关于`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆