Location.getCurrentPositionAsync()与Promise.race兼容问题及超时异常排查
问题排查与解决方案
核心问题分析
- fetchWithTimeout错误处理缺陷:当前实现中,
fetchWithTimeout捕获错误后仅调用alertFunction,未重新抛出错误,导致上层onFindMe通过判断currentLoco是否为undefined抛出通用错误,无法区分是超时还是位置请求本身失败。 - Location.getCurrentPositionAsync的特性:该方法默认无明确超时限制,且可能优先使用缓存位置快速resolve,导致你的10秒超时逻辑无法触发;另外若未获取位置权限,它会立即reject,造成
catch块快速执行。 - badConnection函数冗余:函数返回的React组件不会被渲染,属于无效代码。
分步解决方案
1. 修复fetchWithTimeout的错误传递
修改fetchWithTimeout,在捕获错误后重新抛出,让上层onFindMe的catch块能直接捕获原始错误:
export async function fetchWithTimeout(request, TIMEOUT_SEC, alertFunction) { try { const res = await Promise.race([request, timeout(TIMEOUT_SEC)]); return res; } catch (e) { alertFunction(); throw e; // 重新抛出错误,传递给上层处理 } }
2. 完善位置请求的权限与参数配置
在调用getCurrentPositionAsync前先请求权限,并配置自身超时(略长于你的10秒超时)、禁用缓存,确保超时逻辑能触发:
const onFindMe = async () => { try { setIsLoading(true); // 先请求位置权限 const { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { throw new Error('位置权限未授予'); } // 配置位置请求参数:禁用缓存、设置自身超时为11秒(比自定义超时久) const locationPromise = Location.getCurrentPositionAsync({ maximumAge: 0, // 不使用缓存,强制获取最新位置 timeout: 11000, // 单位:毫秒,确保自定义超时先触发 }); let currentLoco = await fetchWithTimeout( locationPromise, 10, badConnection ); setIsLoading(false); setPosition(positionObjectCreator(currentLoco)); } catch (err) { setIsLoading(false); setError(err); couldntFindYourPosition(); } };
3. 简化badConnection函数
移除无用的React组件返回值:
export const badConnection = () => { Alert.alert( "aww shucks!", "Your internet connection is a bit dodgy, so this feature doesn't work at the moment", [ { text: "OK", style: "ok", }, ] ); };
验证方法
- 测试超时:将
fetchWithTimeout的超时时间设为0.1秒(TIMEOUT_SEC: 0.1),此时位置请求大概率无法在0.1秒内完成,会触发badConnection的弹窗。 - 测试权限拒绝:拒绝位置权限请求,此时会触发
onFindMe的catch块,抛出"位置权限未授予"的错误。
内容的提问来源于stack exchange,提问作者MattCouthon
相关产品推荐
相关产品推荐

