如何使用JavaScript/Node.js递归调用API的nextLink获取全部分页数据
实现思路
- 核心逻辑是判断接口返回结果中是否存在
nextLink,存在则继续发起请求,直到nextLink为空/不存在(即到达最后一页) - 逐页收集返回的
data数组内容,最终合并为完整数据集 - 建议额外增加异常重试、速率控制逻辑,避免请求过于频繁触发接口限流
递归实现方案(基于axios)
先安装依赖:npm install axios
const axios = require('axios'); /** * 递归拉取全量分页数据 * @param {string} currentUrl 当前要请求的分页地址 * @param {Array} allData 已收集的总数据集 * @returns {Promise<Array>} 全量数据集合 */ async function fetchAllData(currentUrl, allData = []) { try { const response = await axios.get(currentUrl); const { data, links, totalRecords } = response.data; // 合并当前页数据到总集合 allData.push(...data); console.log(`已拉取${allData.length}条,总目标${totalRecords}条`); // 存在下一页则递归调用,否则返回总数据 if (links.nextLink) { return fetchAllData(links.nextLink, allData); } else { return allData; } } catch (error) { console.error(`请求${currentUrl}失败:`, error.message); // 可在此处增加失败重试逻辑,比如重试3次失败后再抛出错误 throw error; } } // 调用示例 (async () => { try { const fullData = await fetchAllData('http://example-api.com/data?api_key&page=0&size=10'); console.log('全量数据拉取完成,总条数:', fullData.length); // 后续业务逻辑 } catch (err) { console.error('拉取流程失败:', err); } })();
更稳妥的循环实现(无调用栈溢出风险)
如果分页数量极多,递归可能存在调用栈溢出风险,更推荐使用循环实现:
const axios = require('axios'); async function fetchAllData(firstPageUrl) { let currentUrl = firstPageUrl; const allData = []; while (currentUrl) { try { const response = await axios.get(currentUrl); const { data, links, totalRecords } = response.data; allData.push(...data); console.log(`已拉取${allData.length}条,总目标${totalRecords}条`); // 更新下一页地址,无下一页则退出循环 currentUrl = links.nextLink || null; // 可增加固定延时降低请求速率,避免触发限流 await new Promise(resolve => setTimeout(resolve, 100)); } catch (error) { console.error(`请求${currentUrl}失败,1秒后重试:`, error.message); await new Promise(resolve => setTimeout(resolve, 1000)); } } return allData; }
注意事项
- 若接口有明确的请求频率限制,需额外增加速率控制逻辑,避免IP被封禁
- 数据量较大时不要全量存储在内存中,可逐页写入本地文件或数据库,降低内存占用
- 可按需增加中断逻辑,比如拉取到指定条数后直接终止流程,不需要拉取全部数据
内容的提问来源于stack exchange,提问作者CodeTzu
相关产品推荐
相关产品推荐

