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

API首次调用未更新变量,二次调用才返回正确值的问题解决

修复Yahoo Finance API异步数据加载导致返回值延迟的问题

问题分析

你的loadData函数出现首次请求返回空值、二次请求返回旧数据的问题,核心原因是没有正确处理yahooFinance.historical的异步特性:

  • yahooFinance.historical是回调式异步函数,调用后会立刻执行后续的updateValues()和return语句,此时回调还没完成数据获取,returnValue还是初始空数组
  • 等回调执行完更新returnValue时,函数已经返回了结果,所以下次请求才会用到更新后的数据
  • 全局变量returnValue还会导致不同请求之间的状态污染,进一步加重数据错误

解决方案

改用Promise封装异步逻辑,去掉全局变量,确保数据加载完成后再返回结果。以下是两种可行的修改方案:

方案1:用Promise封装回调函数

const yahooFinance = require("yahoo-finance");

const loadData = (symbol, from, to, freq) => {
    return new Promise((resolve, reject) => {
        yahooFinance.historical(
            {
                symbol: symbol,
                from: from,
                to: to,
                freq: freq,
            },
            (error, quotes) => {
                if (error) {
                    console.error("Error in server/indicatorCalc/parent_calc.js", error);
                    reject(error);
                    return;
                }

                // 直接在回调内处理数据,无需全局变量
                const open = [];
                const close = [];
                const high = [];
                const low = [];
                const volume = [];

                quotes.forEach((e) => {
                    open.push(e.open);
                    close.push(e.adjClose);
                    high.push(e.high);
                    low.push(e.low);
                    volume.push(e.volume);
                });

                console.log("Data loaded in parent_calc.js");
                resolve({ open, close, high, low, volume });
            }
        );
    });
};

module.exports = { loadData };

方案2:用async/await简化(如果yahoo-finance支持Promise)

很多回调风格的库支持省略回调直接返回Promise,这样可以用async/await让代码更简洁:

const yahooFinance = require("yahoo-finance");

const loadData = async (symbol, from, to, freq) => {
    try {
        const quotes = await yahooFinance.historical({
            symbol: symbol,
            from: from,
            to: to,
            freq: freq,
        });

        const open = [];
        const close = [];
        const high = [];
        const low = [];
        const volume = [];

        quotes.forEach((e) => {
            open.push(e.open);
            close.push(e.adjClose);
            high.push(e.high);
            low.push(e.low);
            volume.push(e.volume);
        });

        console.log("Data loaded in parent_calc.js");
        return { open, close, high, low, volume };
    } catch (error) {
        console.error("Error in server/indicatorCalc/parent_calc.js", error);
        throw error;
    }
};

module.exports = { loadData };

API端点调用修改

对应的Express路由需要改成异步处理,确保等待数据加载完成后再响应:

// 示例Express路由
app.get('/indicatorParent/', async (req, res) => {
    try {
        // 根据你的实际参数结构获取请求参数
        const { symbol, from, to, freq } = req.query;
        const data = await loadData(symbol, from, to, freq);
        res.json(data);
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

关键修改点

  • 移除全局变量returnValue,避免请求间的状态污染
  • 用Promise/async-await确保异步操作完成后再返回结果
  • 用forEach替代map处理数据(map是用于生成新数组,这里只是遍历push,forEach更合适)
  • 错误处理更规范,把错误传递给调用方而非仅打印

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:20:28