`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起

Posted

技术标签:

【中文标题】`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起【英文标题】:`navigator.geolocation.getCurrentPosition()` hangs on iOS PWA 【发布时间】:2021-06-10 16:20:17 【问题描述】:

我有这个sn-p:

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 Websites) 设置为:Ask Next Time,@ 987654329@ promise 挂起并且不会超时、解决或拒绝。它不会像在 iOS Safari 浏览器中那样提示我输入我的位置

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

我希望能够处理用户在使用 PWA 时将其设置设置为 Ask Next Time 的情况。

【问题讨论】:

【参考方案1】:

一旦我和一些同事想通了,这个问题的解决方案就相当简单了:

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

这是怎么回事?

    我们正在创建一个空的 promise 数组 如果导航器被标识为standalone,我们将在 4 秒后创建一个 rejects 的 promise(此值是任意的,您希望用户等待的最长时间)并将其推送到 promiseArray。 我们正在创建另一个承诺,它会获取用户的位置并将其推送到 promiseArray 中。 然后我们返回一个从Promise.race() 的执行返回的promise。这里的关键是,如果导航器不是standalonepromiseArray 中将只有一个承诺,因此将按预期工作。如果导航器是独立的,那么promiseArray 中将有两个承诺,Promise.race() 将从超时拒绝,从而拒绝getUserPosition() 函数。

【讨论】:

以上是关于`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起的主要内容,如果未能解决你的问题,请参考以下文章