首页 > web前端 > js教程 > 正文

API分页数据循环获取教程

霞舞
发布: 2025-11-19 16:04:14
原创
216人浏览过

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 < totalAvailable):

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

    Kits AI
    Kits AI

    Kits.ai 是一个为音乐家提供一站式AI音乐创作解决方案的网站,提供AI语音生成和免费AI语音训练

    Kits AI 413
    查看详情 Kits AI
    • 在每次循环中,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 < totalAvailable,还增加了一个 if (currentBatch.length === 0 && allResults.length < totalAvailable) 的判断。这可以防止在API报告的总数与实际可返回数据不一致时(例如,API总数计算错误或数据在分页过程中被删除)陷入无限循环。如果API返回空数据批次但总数仍指示有更多数据,则提前终止。
  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速率限制等因素,以确保应用程序的稳定性和可靠性。

以上就是API分页数据循环获取教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号