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

JS中如何让async异步函数在另一个异步函数执行完成后运行?

问题核心原因

你的基础逻辑方向是对的,出现异常的核心是几个细节错误导致定位逻辑提前抛出错误,终止了正常执行流程:

  • AJAX 函数加了export关键字,若你未将脚本声明为ES模块,会直接抛出语法错误进入catch块
  • API请求URL中使用了HTML转义字符&而非原生&,导致请求参数识别失败
  • 未在定位失败的分支中处理天气请求逻辑

修复方案

1. 完整可运行代码

const WEATHER_API_KEY = "f19d6e315954bfb123e794ab55aa28c4";

const state = {
    location: {
        // 巴黎默认坐标
        lat: 48.8566969,
        lng: 2.3514616
    }
};

// 定位配置项
const options = {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 0
};

// 封装定位Promise
const getPosition = function () {
    return new Promise(function (resolve, reject) {
        navigator.geolocation.getCurrentPosition(resolve, reject, options);
    });
};

// 请求超时工具函数
const TIMEOUT_SEC = 5;
const timeout = function (s) {
    return new Promise(function (_, reject) {
        setTimeout(function () {
            reject(new Error(`请求超时,超过${s}秒`));
        }, s * 1000);
    });
};

// AJAX请求工具,移除冗余的export和method判断逻辑
const AJAX = async function (url) {
    try {
        const fetchPro = fetch(url);
        const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]);
        const data = await res.json();

        if (!res.ok) throw new Error(`${data.message} (${res.status})`);
        return data;
    } catch (err) {
        throw err;
    }
};

// 统一封装天气请求逻辑,复用代码
const fetchWeather = async () => {
    // 替换URL中的转义字符&为原生&
    const weatherData = await AJAX(
        `https://api.openweathermap.org/data/2.5/onecall?lat=${state.location.lat}&lon=${state.location.lng}&units=metric&appid=${WEATHER_API_KEY}`
    );
    console.log('天气数据:', weatherData);
    // 此处补充UI更新逻辑
}

const loadData = async function () {
    try {
        // 等待用户授权和定位结果
        const { coords } = await getPosition();
        const { latitude, longitude } = coords;
        state.location.lat = latitude;
        state.location.lng = longitude;
        console.log('定位成功,使用用户当前坐标');
    } catch (err) {
        // 定位失败(用户拒绝、超时、浏览器不支持)时使用默认坐标
        console.error('定位失败,使用默认巴黎坐标:', err.message);
    } finally {
        // 无论定位成功失败,统一触发天气请求
        await fetchWeather();
    }
};

window.addEventListener("load", loadData);

2. 疑问解答

  • 关于异步执行顺序:async/await 串行调用是严格按代码顺序执行的,只要前一个await没有抛出错误,一定会等待执行完成再运行下一行代码,不存在顺序错乱的问题。你遇到的未等授权就发请求的现象,本质是定位逻辑提前报错跳出了try块。
  • 关于定位失败的处理:可以在catch块中直接调用天气API,使用finally块统一执行请求逻辑更简洁,避免重复代码。
  • 关于返回值获取:修复语法错误后,await getPosition() 会正常返回定位结果,你可以正常拿到经纬度赋值到state中。

内容的提问来源于stack exchange,提问作者halbmond

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:57:04