如何在现有代码中获取API全部19页数据而非仅第一页?
批量获取API多页数据的解决方案
下面的改动几乎不会影响你已有的功能,仅新增多页请求逻辑并替换原有单页请求部分:
1. 新增批量请求函数
先加一个独立函数来处理所有页面的请求,和原有代码完全解耦:
// 批量获取所有页面的鸟类记录 async function fetchAllBirdRecordings() { const baseUrl = "https://xeno-canto.org/api/2/recordings?query=cnt:belgium"; // 先请求第一页拿总页数(如果确定是19页,直接写const totalPages = 19也行) const firstPageResponse = await fetch(baseUrl); const firstPageData = await firstPageResponse.json(); const totalPages = firstPageData.numPages; // 生成所有页面的请求任务 const pagePromises = []; for (let page = 1; page <= totalPages; page++) { pagePromises.push( fetch(`${baseUrl}&page=${page}`).then(res => res.json()) ); } // 等所有请求完成,合并所有记录 const allPagesData = await Promise.all(pagePromises); return allPagesData.flatMap(pageData => pageData.recordings); }
2. 修改init里的数据获取逻辑
把原来的单页fetch换成调用上面的新函数,原有数据处理、渲染逻辑完全保留:
function init() { // 替换原有的单页请求代码 fetchAllBirdRecordings() .then(function (allRecordings) { // 复用你原来的遍历逻辑,现在处理所有页面的记录 allRecordings.forEach(function (recording) { const bird = new Bird(recording.date, recording.lat, recording.lng, recording.en, recording.file); birdList.push(bird); render(bird.HTMLstring); }); }) .then(function () { sorting(); searching(); }) .catch(function (error) { console.error("获取数据失败:", error); }); // 地图初始化代码完全不动 map = new maptalks.Map("map", { center: [4.400528, 50.499861], zoom: 8, baseLayer: new maptalks.TileLayer("base", { urlTemplate: "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", subdomains: ["a", "b", "c", "d"], attribution: '© <a href="http://www.osm.org/copyright">OSM</a> contributors, ' + '&copy; <a href="https://carto.com/attributions">CARTO</a>', }), }); layer = new maptalks.VectorLayer("vector").addTo(map); }
改动优势
- 原有排序、搜索、地图交互、音频播放等功能一行都不用改,完全复用。
- 批量请求逻辑封装在独立函数里,即使出问题,也不会影响已有的功能模块。
- 加了错误捕获,方便排查请求失败的问题。
完整修改后的代码
import Bird from "./Bird.js"; let map; let layer; let point; let birdList = []; let filteredBirdList = []; let clickTimeout = null; const clickDelay = 300; // 批量获取所有页面的鸟类记录 async function fetchAllBirdRecordings() { const baseUrl = "https://xeno-canto.org/api/2/recordings?query=cnt:belgium"; // 先请求第一页拿总页数(如果确定是19页,直接写const totalPages = 19也行) const firstPageResponse = await fetch(baseUrl); const firstPageData = await firstPageResponse.json(); const totalPages = firstPageData.numPages; const pagePromises = []; for (let page = 1; page <= totalPages; page++) { pagePromises.push( fetch(`${baseUrl}&page=${page}`).then(res => res.json()) ); } const allPagesData = await Promise.all(pagePromises); return allPagesData.flatMap(pageData => pageData.recordings); } function init() { // 替换原有的单页请求代码 fetchAllBirdRecordings() .then(function (allRecordings) { // 复用你原来的遍历逻辑,现在处理所有页面的记录 allRecordings.forEach(function (recording) { const bird = new Bird(recording.date, recording.lat, recording.lng, recording.en, recording.file); birdList.push(bird); render(bird.HTMLstring); }); }) .then(function () { sorting(); searching(); }) .catch(function (error) { console.error("获取数据失败:", error); }); // 地图初始化代码完全不动 map = new maptalks.Map("map", { center: [4.400528, 50.499861], zoom: 8, baseLayer: new maptalks.TileLayer("base", { urlTemplate: "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", subdomains: ["a", "b", "c", "d"], attribution: '© <a href="http://www.osm.org/copyright">OSM</a> contributors, ' + '&copy; <a href="https://carto.com/attributions">CARTO</a>', }), }); layer = new maptalks.VectorLayer("vector").addTo(map); } //FUNCTIES VOOR SORTEREN/FILTEREN function sorting() { const nameButton = document.getElementById("sortByName"); const dateButton = document.getElementById("sortByDate"); nameButton.addEventListener("click", function () { document.querySelector("#allBirds-list").innerHTML = ""; birdList.sort(function (birdOne, birdTwo) { if (birdOne.name > birdTwo.name) { return 1; } else { return -1; } }); birdList.forEach(function (bird) { render(bird.HTMLstring); }); }); dateButton.addEventListener("click", function () { document.querySelector("#allBirds-list").innerHTML = ""; birdList.sort(function (birdOne, birdTwo) { if (birdOne.date > birdTwo.date) { return 1; } else { return -1; } }); birdList.forEach(function (bird) { render(bird.HTMLstring); }); }); } function searching() { const field = document.getElementById("inputField"); field.addEventListener("input", function (event) { const input = event.target.value; filteredBirdList = birdList.filter(function (bird) { if (input == bird.name) { return true; } }); document.querySelector("#allBirds-list").innerHTML = ""; filteredBirdList.forEach(function (bird) { render(bird.HTMLstring); }); console.log(filteredBirdList); }); } //FUNCTIES VOOR DE KAART function addMarker(lat, lng, name) { console.log("pin"); point = new maptalks.Marker([lng, lat], { visible: true, editable: true, cursor: "pointer", draggable: false, dragShadow: false, // display a shadow during dragging drawOnAxis: null, // force dragging stick on a axis, can be: x, y symbol: { textFaceName: "sans-serif", textName: name, textFill: "#34495e", textHorizontalAlignment: "right", textSize: 13, }, }); point.addTo(layer); } //FUNCTIES VOOR DE SELECTIE ACTIE window.clicking = function (name, rec, lat, lng) { if (clickTimeout !== null) { clearTimeout(clickTimeout); clickTimeout = null; doubleClick(name, rec, lat, lng); } else { clickTimeout = setTimeout(() => { singleClick(rec); clickTimeout = null; }, clickDelay); } }; function singleClick(rec) { console.log("enkel"); playRecording(rec); } function doubleClick(name, rec, lat, lng) { console.log("dubbel"); document.querySelector("#myGarden-list").innerHTML += `<button> ${name} </button> </br>`; playOnRepeat(rec); addMarker(lat, lng, name); } //FUNCTIES VOOR HET AFSPELEN VAN HET GELUID window.playOnRepeat = function (audioFile) { const audio = new Audio(audioFile); audio.loop = true; audio.play(); }; window.playRecording = function (audioFile) { //console.log(audioFile); const audio = new Audio(audioFile); audio.play(); }; //FUNCTIES VOOR HET WEERGEVEN VAN DE KNOPPEN function render(content) { document.querySelector("#allBirds-list").innerHTML += content; } init();
内容的提问来源于stack exchange,提问作者Broeckie
相关产品推荐
相关产品推荐

