`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起 [英] `navigator.geolocation.getCurrentPosition()` hangs on 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 Time
,getCurrentPosition()
承诺挂起并且不会超时、解决或拒绝.它不会像在 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
如果我将设置更改为 Never
或 While 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>;
}
这是怎么回事?
- 我们正在创建一个空的承诺数组
- 如果导航器被标识为
standalone
,我们将创建一个承诺,在 4 秒后rejects
(该值是任意的,您希望用户使用的最长时间)等待)并将其推送到 promiseArray. - 我们正在创建另一个 promise,它获取用户的位置并将其推送到
promiseArray
中. - 然后我们返回一个从
Promise.race()
的执行返回的承诺.这里的关键是,如果导航器不是standalone
,promiseArray
中将只有一个 promise,因此将按预期工作.如果导航器是独立的,那么promiseArray
中将有两个 promise,Promise.race()
将拒绝超时,从而拒绝getUserPosition()
函数.
- We're creating an empty promise array
- If the navigator is identified as
standalone
, we're creating a promise thatrejects
after 4 seconds (this value is arbitrary, the maximum time you want your users to wait) and pushing it to the promiseArray. - We're creating another promise which gets the user's position and pushing that into the
promiseArray
as well. - 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 thepromiseArray
if the navigator is notstandalone
, and will therefore work as intended. If the navigator is standalone, then there will be two promises in thepromiseArray
and thePromise.race()
will reject from the timeout, thus rejecting fromgetUserPosition()
function.
这篇关于`navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!