Skip to content

Instantly share code, notes, and snippets.

@efstathiosntonas
Created June 7, 2023 07:29
Show Gist options
  • Save efstathiosntonas/18f194e182cb5f6d52cca5a78de0c5f0 to your computer and use it in GitHub Desktop.
Save efstathiosntonas/18f194e182cb5f6d52cca5a78de0c5f0 to your computer and use it in GitHub Desktop.
ExpoGetLocationWithRetry.ts
const locationOptions: LocationOptions = {
accuracy: LocationAccuracy.Balanced,
distanceInterval: 250
};
const lastKnownLocationOptions: LocationLastKnownOptions = {
maxAge: 60000,
requiredAccuracy: 1000
};
const ANDROID_DELAY_IN_MS = 4 * 1000; // 4s
const IOS_DELAY_IN_MS = 15 * 1000; // 15s
const DELAY_IN_MS = Platform.OS === "ios" ? IOS_DELAY_IN_MS : ANDROID_DELAY_IN_MS;
const MAX_TRIES = 3;
function delay(timeInMilliseconds: number) {
return new Promise<null>((resolve) => {
setTimeout(() => resolve(null), timeInMilliseconds);
});
}
function handleLocationError(locationError: Error | null) {
if (!locationError) {
throw new Error("com.xxxx.home.permission_timeout");
}
if (locationError.message.startsWith("Cannot obtain current location:")) {
throw new Error("com.xxxx.home.permission_timeout");
} else if (locationError.message === "Current location not found.") {
throw new Error("com.xxxx.home.location_not_found");
} else if (locationError.message === "Location services are disabled") {
throw new Error("com.xxxx.home.location_services_disabled");
} else if (locationError.message === "No location provider available") {
throw new Error("com.xxxx.home.no_location_provider_available");
}
throw new Error(locationError.message);
}
// using retry logic since get location can silently fail on Android, https://github.com/expo/expo/issues/10756#issuecomment-1483254287
export const getPosition = async () => {
console.log("render");
try {
const lastKnownLocation = await Location.getLastKnownPositionAsync(
lastKnownLocationOptions
);
if (lastKnownLocation) {
const { latitude: lat, longitude: lng } = lastKnownLocation.coords;
return { lat: String(lat), lng: String(lng) };
}
let tries = 1;
let location: LocationObject | null = null;
let locationError: Error | null = null;
do {
tries += 1;
try {
location = await Promise.race([
delay(DELAY_IN_MS),
Location.getCurrentPositionAsync(locationOptions)
]);
if (!location) {
throw new Error("Timeout");
}
} catch (err) {
locationError = err as Error;
}
} while (!location && tries <= MAX_TRIES);
if (!location) {
return handleLocationError(locationError);
}
const { latitude: lat, longitude: lng } = location.coords;
return { lat: String(lat), lng: String(lng) };
} catch (error: any) {
notify(error, "warning", "cannot fetch location", { user_id: currentUser().uid });
switch (error.code) {
case PermissionStatus.DENIED:
throw new Error("com.xxxx.home.permission_denied");
default:
throw error;
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment