讲师中心 微信公众号
AI工具推荐 视频效率加速

API分页数据循环获取教程

星婷大大_8520

星婷大大_8520

发布时间:2025-11-19 16:04:14

|

321人浏览过

|

来源于php中文网

原创

API分页数据循环获取教程

本文详细介绍了如何通过异步循环机制,从支持分页的api中高效、完整地获取所有数据。针对api每次请求返回结果数量受限的场景,教程演示了如何利用javascript的`async/await`和`fetch`,通过动态调整请求参数(如`start`或`page`),并结合api响应中的总数信息,迭代地请求并累积数据,直至所有可用结果被成功检索。

理解API分页与数据检索挑战

在与许多Web API交互时,一个常见的情况是API为了优化性能和管理资源,会限制单次请求返回的数据量。例如,一个搜索API可能每次只返回50条结果,即使总共有数百甚至数千条结果可用。为了获取所有数据,开发者需要执行一系列连续的请求,每次请求获取下一批结果,这个过程被称为“分页”。

挑战在于如何有效地管理这些连续请求:

  1. 如何确定需要执行多少次请求? 通常,API响应会包含一个总结果数。
  2. 如何构建每次请求的URL? 需要根据当前已获取的数据量或页码来调整请求参数,例如start(起始偏移量)或page(页码)。
  3. 如何累积所有请求的数据? 将每次请求返回的数据合并到一个集合中。
  4. 何时停止循环? 当所有可用数据都已获取时,循环应终止。

核心策略:异步循环与动态参数调整

解决上述挑战的关键在于使用一个异步循环结构,它能够:

  1. 逐次发送请求: 每次迭代发送一个API请求。
  2. 等待响应: 使用async/await确保前一个请求完成后再处理数据并发送下一个请求。
  3. 更新请求参数: 根据已获取的数据量或当前循环次数来计算下一个请求的start或page参数。
  4. 累积数据: 将每次请求返回的数据追加到总结果集中。
  5. 判断终止条件: 比较已累积的数据量与API报告的总数据量,决定是否继续循环。

实践示例:使用JavaScript实现API分页数据获取

以下是一个使用JavaScript实现通用API分页数据获取的示例,它模拟了从一个分页API(如Indeed搜索API)获取所有结果的过程。

/**
 * 异步函数,用于从支持分页的API获取所有数据。
 * 假设API的响应结构包含一个指示总结果数的字段(如 'totalResults')
 * 并且支持通过 'start' 和 'limit' 参数进行分页。
 *
 * @param {string} baseUrl API的基础URL,不包含分页参数。
 * @param {object} initialQueryParams 初始查询参数,不包含分页参数。
 * @param {number} limitPerPage 每次请求获取的最大结果数。
 * @param {string} totalResultsKey API响应中表示总结果数的键名。
 * @returns {Promise<Array>} 包含所有从API获取的数据的Promise。
 */
async function fetchAllPaginatedData(baseUrl, initialQueryParams, limitPerPage, totalResultsKey) {
    let allResults = []; // 用于累积所有结果的数组
    let currentOffset = 0; // 当前请求的起始偏移量
    let totalAvailable = Infinity; // 初始设定为无限大,等待API响应提供真实值

    // 转换为URLSearchParams对象,便于管理查询参数
    const params = new URLSearchParams(initialQueryParams);

    // 循环直到所有数据都被获取
    while (allResults.length < totalAvailable) {
        // 设置当前请求的分页参数
        params.set('start', currentOffset.toString());
        params.set('limit', limitPerPage.toString());

        const url = `${baseUrl}?${params.toString()}`;

        try {
            console.log(`Fetching data from: ${url}`);
            const response = await fetch(url);

            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }

            const responseJson = await response.json();

            // 假设API响应的数据字段是 'data',并且总数字段是动态传入的 'totalResultsKey'
            const currentBatch = responseJson.data || [];
            totalAvailable = responseJson[totalResultsKey] || 0; // 更新总可用结果数

            allResults = allResults.concat(currentBatch); // 累积当前批次的数据

            // 更新下一个请求的偏移量
            currentOffset += currentBatch.length;

            // 如果当前批次为空,且allResults.length < totalAvailable,
            // 说明可能API已无更多数据,或者API返回的总数不准确,应终止循环
            if (currentBatch.length === 0 && allResults.length < totalAvailable) {
                console.warn("API returned empty batch but total results suggest more data. Terminating loop to prevent infinite requests.");
                break;
            }

        } catch (error) {
            console.error(`Error fetching data: ${error.message}`);
            // 在实际应用中,这里可能需要更复杂的错误处理,如重试机制
            break; // 遇到错误时终止循环
        }
    }

    console.log(`Finished fetching. Total items collected: ${allResults.length}`);
    return allResults;
}

// 模拟Indeed API的调用
// 注意:以下URL和totalResultsKey是示例,实际Indeed API可能需要认证或其他特定参数
const indeedApiBaseUrl = "https://resumes.indeed.com/rpc/search";
const indeedInitialParams = {
    q: "sales",
    l: "Orlando,FL",
    lmd: "3day",
    radius: "25",
    indeedcsrftoken: "test_tokent" // 示例token
};
const indeedLimit = 50; // Indeed API每次请求的限制
const indeedTotalKey = "totalAvailableResults"; // 假设Indeed API返回的总数键名

// 调用函数并处理结果
(async () => {
    try {
        const allIndeedResults = await fetchAllPaginatedData(
            indeedApiBaseUrl,
            indeedInitialParams,
            indeedLimit,
            indeedTotalKey
        );
        console.log("All Indeed search results:", allIndeedResults);
        // 在这里可以进一步处理所有获取到的数据
    } catch (error) {
        console.error("Failed to fetch all Indeed results:", error);
    }
})();

// 另一个通用API的示例(如问题答案中使用的passenger API)
// 假设该API使用 'page' 和 'size',且总数键名为 'totalPassengers'
const passengerApiBaseUrl = "https://api.instantwebtools.net/v1/passenger";
const passengerInitialParams = {}; // 该API可能不需要初始查询参数
const passengerLimit = 100; // 每次请求的限制
const passengerTotalKey = "totalPassengers"; // API响应中总乘客数的键名

async function fetchAllPaginatedDataByPage(baseUrl, initialQueryParams, limitPerPage, totalResultsKey) {
    let allResults = [];
    let currentPage = 0; // 从第0页开始
    let totalAvailable = Infinity;

    const params = new URLSearchParams(initialQueryParams);

    while (allResults.length < totalAvailable) {
        params.set('page', currentPage.toString());
        params.set('size', limitPerPage.toString());

        const url = `${baseUrl}?${params.toString()}`;

        try {
            console.log(`Fetching data from: ${url}`);
            const response = await fetch(url);
            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }
            const responseJson = await response.json();

            const currentBatch = responseJson.data || [];
            totalAvailable = responseJson[totalResultsKey] || 0;

            allResults = allResults.concat(currentBatch);
            currentPage++; // 切换到下一页

            if (currentBatch.length === 0 && allResults.length < totalAvailable) {
                console.warn("API returned empty batch but total results suggest more data. Terminating loop.");
                break;
            }

        } catch (error) {
            console.error(`Error fetching data: ${error.message}`);
            break;
        }
    }
    console.log(`Finished fetching. Total items collected: ${allResults.length}`);
    return allResults;
}

(async () => {
    try {
        const allPassengers = await fetchAllPaginatedDataByPage(
            passengerApiBaseUrl,
            passengerInitialParams,
            passengerLimit,
            passengerTotalKey
        );
        console.log("All passengers:", allPassengers);
    } catch (error) {
        console.error("Failed to fetch all passengers:", error);
    }
})();

代码解析与注意事项

  1. fetchAllPaginatedData 函数:

    • 这是一个通用的异步函数,接受API的基础URL、初始查询参数、每页限制和表示总结果数的键名。
    • allResults 数组用于存储从所有请求中累积的数据。
    • currentOffset 变量跟踪当前请求的起始位置(对于使用start参数的API)。
    • totalAvailable 变量存储API报告的总结果数,用于判断循环终止条件。
    • URLSearchParams 用于方便地构建和管理URL查询参数。
  2. 循环条件 while (allResults.length

    • 这是循环的核心。只要已收集的结果数量小于API报告的总结果数,就继续请求。
    • 初始时 totalAvailable 设为 Infinity,确保至少会执行一次请求来获取真实的 totalAvailable 值。
  3. 请求参数设置:

    java-api-doc-generator
    java-api-doc-generator

    分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

    下载
    • 在每次循环中,params.set('start', currentOffset.toString()) 和 params.set('limit', limitPerPage.toString()) 更新了分页参数。
    • 对于使用page和size的API,需要相应地调整为params.set('page', currentPage.toString())和params.set('size', limitPerPage.toString()),并递增currentPage。
  4. fetch 和 async/await:

    • await fetch(url) 发送异步请求并等待响应。
    • await response.json() 解析JSON格式的响应体。
    • 使用 try...catch 块来捕获网络错误或API返回的非成功状态码,增强代码健壮性。
  5. 数据累积与偏移量更新:

    • allResults = allResults.concat(currentBatch) 将当前请求获取的数据追加到总结果集中。
    • currentOffset += currentBatch.length 更新偏移量,为下一次请求准备正确的start值。对于页码,则是currentPage++。
  6. 终止条件细化:

    • 除了 allResults.length
  7. 错误处理:

    • 示例中包含了基本的错误日志。在生产环境中,可能需要更复杂的错误处理机制,例如:
      • 重试逻辑: 对于瞬时网络错误或API服务不稳定,可以实现指数退避重试。
      • 用户通知: 向用户显示友好的错误消息。
      • 告警: 将错误记录到日志系统并触发告警。
  8. API特定性:

    • 不同的API可能使用不同的分页参数名称(如offset/limit、page/size、start/count等)。
    • API响应中表示总结果数的键名也可能不同(如total、total_count、meta.total等)。
    • 在实际应用中,你需要根据具体API文档调整这些参数和键名。

总结

通过异步循环结合动态参数调整和API响应中的总数信息,我们可以构建出健壮且高效的JavaScript代码来获取支持分页的API的所有数据。理解async/await、fetch以及如何根据API文档调整分页逻辑是实现这一功能的关键。务必考虑错误处理、API速率限制等因素,以确保应用程序的稳定性和可靠性。

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2195

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3482

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1176

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

4019

2025.09.10

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3468

2023.11.20

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

354

2023.09.25

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

1907

2023.09.19

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

20

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebStorm 官方调试文档
WebStorm 官方调试文档

共0课时 | 0人学习

React 教程
React 教程

共58课时 | 12.4万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 6.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn