使用 Fetch API 以递归方式返回分页输出



总结

我想使用 JavaScript 的 Fetch API 递归地将分页输出整理到数组中。从承诺开始,我认为异步/等待函数会更合适。

尝试

这是我的方法:

global.fetch = require("node-fetch");
async function fetchRequest(url) {
try {
// Fetch request and parse as JSON
const response = await fetch(url);
let data = await response.json();
// Extract the url of the response's "next" relational Link header
let next_page = /<([^>]+)>; rel="next"/g.exec(response.headers.get("link"))[1];
// If another page exists, merge it into the array
// Else return the complete array of paginated output
if (next_page) {
data = data.concat(fetchRequest(next_page));
} else {
console.log(data);
return data;
}
} catch (err) {
return console.error(err);
}
}
// Live demo endpoint to experiment with
fetchRequest("https://jsonplaceholder.cypress.io/posts?_page=9");

对于此演示,它应该产生 2 个请求,这些请求生成一个包含 20 个对象的数组。虽然返回了数据,但我无法理解如何将其整理成一个数组。任何指导将不胜感激。谢谢你的时间。

解决方案#1

感谢@ankit-古普塔:

async function fetchRequest(url) {
try {
// Fetch request and parse as JSON
const response = await fetch(url);
let data = await response.json();
// Extract the url of the response's "next" relational Link header
let next_page;
if (/<([^>]+)>; rel="next"/g.test(response.headers.get("link"))) {
next_page = /<([^>]+)>; rel="next"/g.exec(response.headers.get("link"))[1];
}
// If another page exists, merge its output into the array recursively
if (next_page) {
data = data.concat(await fetchRequest(next_page));
}
return data;
} catch (err) {
return console.error(err);
}
}
fetchRequest("https://jsonplaceholder.cypress.io/posts?_page=9").then(data =>
console.log(data)
);

对于每个页面,后续调用以递归方式进行,并连接到一个数组中。是否有可能使用Promises.all将这些调用并行链接,类似于这个答案?

附带说明一下,为什么StackOverflow片段在第二次获取时失败了?

你需要将next_page包装在一个条件中,否则会导致最后一次调用时出现类型错误(因为/<([^>]+)>; rel="next"/g.exec(response.headers.get("link"))将为空(

在连接数据之前,您需要承诺才能得到解决。

对代码进行一些小的更改可以产生正确的输出:

global.fetch = require("node-fetch");
async function fetchRequest(url) {
try {
// Fetch request and parse as JSON
const response = await fetch(url);
let data = await response.json();
// Extract the url of the response's "next" relational Link header
let next_page;
if(/<([^>]+)>; rel="next"/g.exec(response.headers.get("link")))
next_page = /<([^>]+)>; rel="next"/g.exec(response.headers.get("link"))[1];
// If another page exists, merge it into the array
// Else return the complete array of paginated output
if (next_page) {
let temp_data = await fetchRequest(next_page); 
data = data.concat(temp_data);
}
return data;
} catch (err) {
return console.error(err);
}
}
// Live, demo endpoint to experiment
fetchRequest("https://jsonplaceholder.cypress.io/posts?_page=9").then(data => {
console.log(data);
});

最新更新