Node.js异步请求下while循环无限循环及Express中间件适配问题
解决Node.js异步请求导致while循环无限的问题
问题根源
你的代码中同步while循环和异步request回调的执行逻辑不兼容:while是同步执行的,会瞬间发起大量请求,完全不会等待回调函数填充数组,导致数组长度始终满足循环条件,陷入无限循环。
解决方案
1. 改用Promise风格的请求库(推荐)
request库已被废弃,建议使用原生支持Promise的axios或node-fetch,结合async/await实现异步循环,同时Express完全支持异步中间件(只需正确处理错误)。
示例代码(使用axios)
const axios = require('axios'); // 定义异步Express中间件 async function fetchFilteredData(req, res, next) { let filteredResults = []; let currentApiUrl = searchLink.apiLink; try { while (filteredResults.length <= 10) { // 等待请求完成 const response = await axios.get(currentApiUrl); const apiData = response.data; // 过滤符合条件的数据 const validItems = apiData.results.filter(item => item.title !== null && item.description !== null && item.content !== null && item.language === "english" ); filteredResults.push(...validItems); // 检查是否有下一页,没有则终止循环 if (!apiData.nextPage) break; // 更新下一页URL currentApiUrl = `${searchLink.apiLink}&page=${apiData.nextPage}`; } // 将结果返回给客户端 res.json(filteredResults); } catch (error) { // 捕获错误并传递给Express错误处理中间件 next(new Error(`API请求错误: ${error.message}`)); } } // 在路由中使用该中间件 app.get('/filtered-data', fetchFilteredData);
2. 兼容旧版request库(使用promisify)
如果必须使用request,可以用Node.js内置的util.promisify将其转换为Promise风格:
const request = require('request'); const { promisify } = require('util'); const requestAsync = promisify(request); async function fetchFilteredData(req, res, next) { let filteredResults = []; let currentApiUrl = searchLink.apiLink; try { while (filteredResults.length <= 10) { // 等待请求完成,开启json参数自动解析响应 const { body: apiData } = await requestAsync({ url: currentApiUrl, json: true }); const validItems = apiData.results.filter(item => item.title !== null && item.description !== null && item.content !== null && item.language === "english" ); filteredResults.push(...validItems); if (!apiData.nextPage) break; currentApiUrl = `${searchLink.apiLink}&page=${apiData.nextPage}`; } res.json(filteredResults); } catch (error) { next(new Error(`API请求错误: ${error.message}`)); } }
关键说明
- Express异步中间件:Express支持异步函数作为中间件,只需在函数内部用
try/catch捕获错误,并调用next(err)传递给错误处理中间件即可,无需纠结“标准函数”限制。 - 顶层await问题:CommonJS模块(
.js)不支持顶层await,必须将逻辑包裹在异步函数中执行;若要使用顶层await,需将文件改为ES模块(.mjs或在package.json中设置"type": "module")。 - 循环终止条件:务必添加
nextPage存在性检查,避免在API无下一页时继续发起无效请求。
内容的提问来源于stack exchange,提问作者Sourabrata Bose
相关产品推荐
相关产品推荐

