如何打印分页形式的《权力的游戏》 API 中的所有角色名称 |在 JS 中遍历分页 API



您好,我正在尝试使用《权力的游戏》API制作一个副项目。出于好奇,我想打印 https://www.anapioficeandfire.com/api/characters 中的所有角色名称。

从响应标头和文档 (https://anapioficeandfire.com/Documentation#pagination( 中,我看到这个 API 有 214 页。 如何从所有这 214 个页面中获取角色名称。

我当前的尝试允许我仅从第一个 10 个对象中获取名称

这是我的尝试:

(function() {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(req.getResponseHeader("link"));
let charObj = JSON.parse(this.responseText);
for (let i = 0; i < charObj.length; i++) {
let p = document.createElement("p");
let name = document.createTextNode(charObj[i].name);
p.appendChild(name);
document.body.appendChild(p);
}
}
};
req.open("GET", "https://www.anapioficeandfire.com/api/characters", true);
req.send();
})();

在文档中,您可以看到您可以指定page numberpageSize,但是:

  1. 您可以指定每页要接收多少个项目,最大值为 50

通过在url末尾添加这些参数,您每页最多可以获得 50 个项目,添加page=1&pageSize=50(因为原始页面大小为10(

但是您可以将您的请求放在一个循环中,一次10一次获取从1214的所有页面:

(松开 IFEE 并在 for 循环中调用函数(

function getItems(page) {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//console.log(req.getResponseHeader("link"));
let charObj = JSON.parse(this.responseText);
for (let i = 0; i < charObj.length; i++) {
let p = document.createElement("p");
let name = document.createTextNode(charObj[i].name);
p.appendChild(name);
document.body.appendChild(p);
}
}
};
req.open("GET", "https://www.anapioficeandfire.com/api/characters?page=" + page + "&pageSize=10", true);
req.send();
};
for (let i = 1; i <= 214; i++) {
getItems(i)
}

使用fetch. 有一个link标头属性,用于告诉您正在查看的端点的nextprevlastURL。

您应该以这样一种方式链接/排序请求:获取第一个 URL,获取nextURL,然后调用下一页。 继续这样做,直到你用完页面并以这种方式收集所有字符。

我注意到不是每个人都有name,所以我要么拉名字,要么拉第一个别名。

此外,为了简化对服务器的访问,我将该过程的深度限制为 3 个请求。 如果您不想要限制,则应将其删除。

function parseHeaders(res) {
return res.headers.get("link").split(",").reduce((acc, link) => {
const props = /^<(.+)>; rel="(.+)"$/.exec(link.trim());
if (!props) {
console.warn("no match");
return acc;
}
acc[props[2]] = props[1];
return acc;
}, {});
}
async function go(url, depth = 0) {
/*
* You don't need this, this is just to alleviate load on the API's server
* You should remove all the stuff about depth whenever you use this,
* it just limits the total number of requests to fire to 3 which is nice
* since it looks like there would be like 215 requests if you didn't do this.
*/
if (depth >= 3) return [];
const res = await fetch(url);
const props = parseHeaders(res);
const data = await res.json();
const characters = data.map(character => character.name || character.aliases[0]);
if (props.next) {
const newCharacters = await go(props.next, depth + 1);
characters.push(...newCharacters);
}
return characters;
}
(async function() {
const characters = await go("https://www.anapioficeandfire.com/api/characters");
console.log(characters);
}());

最新更新