使用Promise处理分页REST API的状态码作用域与数组扁平化问题咨询
分页API全量数据获取的问题修复方案
原代码的核心问题
- 异步循环控制失效:do-while是同步循环,发起请求后立刻判断循环条件,但此时API请求还没完成,
statusCode根本没被异步回调修改,导致循环无法正确判断是否需要继续请求下一页。 - 返回二维数组:收集所有请求的Promise后用
Promise.all()返回,每个Promise对应一页的workers数组,最终结果自然是二维的,需要额外调用flat()处理。
修复后的完整代码
exports.get_workers = async (access_token, certificate, private_key) => { let page = 0; const pageSize = 2; const allWorkers = []; while (true) { try { const workersPage = await new Promise((resolve, reject) => { const options = { hostname: 'accounts.adp.com', path: `/hr/v2/workers?$top=${pageSize}&$skip=${page * pageSize}`, method: 'GET', headers: { 'Accept': 'application/json;masked=false', 'Authorization': `Bearer ${access_token}` }, cert: certificate, key: private_key, }; const req = require('https').request(options, (res) => { // 处理错误状态码(除了204) if (res.statusCode < 200 || (res.statusCode >= 300 && res.statusCode !== 204)) { reject(new Error(`请求失败: HTTP ${res.statusCode}`)); return; } // 204代表无更多数据,返回空数组终止循环 if (res.statusCode === 204) { resolve([]); return; } const body = []; res.on('data', chunk => body.push(chunk)); res.on('end', () => { const parsedData = JSON.parse(Buffer.concat(body).toString()); resolve(parsedData.workers); }); }); req.on('error', err => reject(`网络错误: ${err.message}`)); req.end(); }); // 无数据则退出循环 if (workersPage.length === 0) break; // 合并当前页数据到总数组(一维) allWorkers.push(...workersPage); page++; } catch (err) { throw new Error(`获取第${page}页数据失败: ${err}`); } } return allWorkers; };
关键修复点说明
1. 解决异步循环的状态码判断问题
- 改用异步while循环,通过
await等待每一页请求完成后,再处理下一页。这样能确保我们拿到当前请求的真实状态,判断是否还有后续数据。 - 把状态码的处理逻辑直接放到Promise内部:如果返回204,就resolve空数组,外部循环检测到空数组就终止;其他错误状态直接抛出异常,避免无效循环。
- 彻底抛弃了依赖外部变量传递状态码的方式,从根源上解决异步同步不匹配的问题。
2. 直接返回一维数组
- 初始化一个总数组
allWorkers,每拿到一页的workers数据,用扩展运算符...把单页的每个元素直接追加到总数组里(allWorkers.push(...workersPage)),这样总数组始终是一维结构。 - 函数最终直接返回这个总数组,调用方不需要再做
flat()处理。
内容的提问来源于stack exchange,提问作者craig
相关产品推荐
相关产品推荐

