#javascript #ios #typescript #progressive-web-apps #w3c-geolocation
Вопрос:
У меня есть этот фрагмент:
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
, getCurrentPosition()
обещание зависает и не истекает, не разрешается или не отклоняется. Он не запрашивает у меня мое местоположение, как это происходит в браузере Safari iOS
Если я изменю настройки на Never
или While Using the App
, он предложит мне и будет работать нормально.
Я хочу иметь возможность обрабатывать сценарий, в котором пользователь установил свои настройки Ask Next Time
при использовании PWA.
Ответ №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>;
}
Что здесь происходит?
- Мы создаем пустой массив обещаний
- Если навигатор идентифицирован как
standalone
, мы создаем обещание, чтоrejects
через 4 секунды (это произвольное значение, максимальное время, которое вы хотите, чтобы ваши пользователи ждали), и отправляем его в поле PromiseArray. - Мы создаем еще одно обещание, которое определяет позицию пользователя и подталкивает его к тому
promiseArray
же. - Затем мы возвращаем обещание, которое возвращается после выполнения
Promise.race()
. Ключ здесь в том , что вpromiseArray
случае, если навигатора нет, будет только одно обещаниеstandalone
, и поэтому он будет работать так, как задумано. Если навигатор является автономным, то в нем будет два обещания,promiseArray
иPromise.race()
он будет отклонен из тайм-аута, тем самым отказавшись отgetUserPosition()
функции.