Node后端如何存储request请求返回值以完成批量接口调用?
解决Node.js中异步request请求结果无法存储的问题
你遇到的核心问题是异步代码的执行顺序问题:request是基于回调的异步函数,当你尝试把回调里的sum赋值给外部变量theSum时,回调函数还没执行(请求还没完成),所以theSum根本拿不到正确的值。而且回调里的return sum只能返回给request内部,没法传递到外部作用域。
下面给你两种靠谱的解决方案,都是用Promise + async/await来处理异步逻辑,让代码更清晰,同时能正确收集所有请求结果:
方案一:将request封装为Promise,并行处理所有请求(高效)
首先把回调式的request包装成Promise,这样就能用async/await来等待请求完成:
const request = require('request'); // 封装request为Promise函数,传入请求配置和费率,返回计算后的sum function fetchAndCalculateSum(options, theRate) { return new Promise((resolve, reject) => { request(options, (error, response, body) => { if (error) { // 请求失败时抛出错误 return reject(new Error(`Request failed: ${error.message}`)); } console.log(`Response: ${response.statusCode} ${response.statusMessage}`); try { const bodyData = JSON.parse(body); const sum = bodyData.fields.timetracking.originalEstimateSeconds / 3600 * theRate; // 请求成功时返回计算后的sum resolve(sum); } catch (parseError) { // 处理JSON解析错误 reject(new Error(`Failed to parse response: ${parseError.message}`)); } }); }); }
然后在你的接口路由里,用async/await结合Promise.all来并行处理所有Adhoc数据的请求,最后收集结果返回:
// 假设这是你的Express路由处理函数(需要标记为async) app.get('/your-adhoc-sum-api', async (req, res) => { try { // 1. 从数据库获取所有Adhoc数据的_id(这里假设用MongoDB的Mongoose,你可以换成自己的数据库查询逻辑) const adhocList = await Adhoc.find({}, { _id: 1 }); // 只查询_id字段,提升效率 // 2. 为每个Adhoc生成请求Promise const sumPromises = adhocList.map(async (adhoc) => { // 根据当前adhoc的_id构建request的配置(这里需要你补充具体的url和其他参数) const requestOptions = { url: `https://your-target-api.com/data/${adhoc._id}`, // 示例URL method: 'GET', headers: { // 如果需要请求头,比如Authorization,在这里添加 } }; // 等待当前请求完成,拿到sum值 const sum = await fetchAndCalculateSum(requestOptions, theRate); // theRate是你的费率变量 // 返回需要的格式对象 return { id: adhoc._id.toString(), sum }; // 把ObjectId转为字符串,方便前端处理 }); // 3. 等待所有请求完成,拿到所有结果 const finalResult = await Promise.all(sumPromises); // 4. 返回结果给前端 res.json(finalResult); } catch (error) { // 处理所有可能的错误(数据库查询失败、请求失败、JSON解析失败等) console.error('API Error:', error); res.status(500).json({ message: 'Internal Server Error', error: error.message }); } });
方案二:顺序处理请求(适合有API频率限制的场景)
如果你的目标API有请求频率限制,不想同时发起太多请求,可以用for...of循环顺序执行每个请求:
app.get('/your-adhoc-sum-api', async (req, res) => { try { const adhocList = await Adhoc.find({}, { _id: 1 }); const finalResult = []; // 用for...of顺序遍历,确保前一个请求完成后再发下一个 for (const adhoc of adhocList) { const requestOptions = { url: `https://your-target-api.com/data/${adhoc._id}`, // 其他配置... }; const sum = await fetchAndCalculateSum(requestOptions, theRate); finalResult.push({ id: adhoc._id.toString(), sum }); } res.json(finalResult); } catch (error) { console.error('API Error:', error); res.status(500).json({ message: 'Internal Server Error', error: error.message }); } });
为什么这样能解决问题?
- Promise把异步回调转换成了可以被
await等待的对象,让异步代码的执行顺序变得可控。 async/await让异步代码看起来和同步代码一样直观,避免了回调嵌套(回调地狱)。Promise.all可以并行处理所有请求,大幅提升接口响应速度;而for...of则适合需要严格顺序的场景。
内容的提问来源于stack exchange,提问作者George Ponta
相关产品推荐
相关产品推荐

