You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Location.getCurrentPositionAsync()与Promise.race兼容问题及超时异常排查

问题排查与解决方案

核心问题分析

  1. fetchWithTimeout错误处理缺陷:当前实现中,fetchWithTimeout捕获错误后仅调用alertFunction,未重新抛出错误,导致上层onFindMe通过判断currentLoco是否为undefined抛出通用错误,无法区分是超时还是位置请求本身失败。
  2. Location.getCurrentPositionAsync的特性:该方法默认无明确超时限制,且可能优先使用缓存位置快速resolve,导致你的10秒超时逻辑无法触发;另外若未获取位置权限,它会立即reject,造成catch块快速执行。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:14:57