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
相关产品推荐
相关产品推荐

