Return 使用 Fetch 递归分页输出 API

Return paginated output recursively with Fetch API

总结

我想使用 JavaScript 的 Fetch API 递归地将分页输出整理成一个数组。从承诺开始,我认为 async/await 函数会更合适。

尝试

这是我的方法:

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-gupta:

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, similar to 并行链接这些调用?

附带说明一下,为什么 Whosebug 代码段在第二次获取时失败?

你需要把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);
});