【问题标题】:use fetch to load paginated data recursively使用 fetch 递归加载分页数据
【发布时间】:2020-03-09 08:17:07
【问题描述】:

我想从此 API 获取数据:“https://swapi.co/api/planets”。数据分页像 https://swapi.co/api/planets/?page=1, https://swapi.co/api/planets/?page=2....

我想构建一个接受 url、页面和回调作为参数的 API。它将逐页获取所有数据,直到到达参数中指定的页面。

例如

function loadData(https://swapi.co/api/planets, 5, cb)

这将从 page1、page2、page3、page4 和 page5 加载数据。

这是我的尝试,但它不起作用。有人可以指出我正确的方向吗?

function fn(url, page, pages, cb) {
  return new Promise((resolve, reject) => {
    const endpoint = `${url}/?page=${page}`;
    fetch(endpoint).then(response => {
      if (response.status !== 200) {
        throw `${response.status} ${response.statusText}`;
      }
      response.json().then(data => {
        cb(data);
        if (page <= pages) {
          fn(url, page + 1, pages, cb)
            .then(resolve)
            .catch(reject);
        } else {
          resolve();
        }
      });
    });
  });
}

function cb(data) {
  console.log(data)
}

fn('https://swapi.co/api/planets', 1, 3, cb).then(() => {});

后续问题:如果我不想传入回调作为参数,而是想传入一个数组来收集加载的数据,我应该如何调整这个 API?

【问题讨论】:

标签: javascript ecmascript-6 frontend


【解决方案1】:

如前所述,您可能不需要等待每次调用完成后再进行下一次调用,但如果您真的想要,我只需要说我发现它更容易解析(作为人类)使用异步/等待。

我在这个 sn-p 中做了一个快速的基本版本供您查看,没有错误处理或检查数据是否正确。也许这种方法可能更适合您?

async function getPage(page) {
  let response = await fetch(`https://swapi.co/api/planets/?page=${page}`);
  let data = await response.json()
  return data;
}


async function getPages(startPage, endPage) {
  let currentPage = startPage;
  let finalArr = [];
  while(currentPage <= endPage) {
    const pageData = await getPage(currentPage);
    console.log('adding page', currentPage);
    finalArr.push(...pageData.results);
    currentPage++;
  }

  console.log(finalArr)
}

getPages(1, 3);

【讨论】:

  • 您好,谢谢您的回答!真的学到了很多。我发现这个问题有点类似于我在这里做的事情。 stackoverflow.com/questions/49129245/… 但他们正在递归地创建一个解决它的承诺。是不是因为每个页面都依赖于之前获取的页面,所以我们必须这样做?
【解决方案2】:

由于每个请求不依赖于前一个,我将使用Promise.all 方法,而不是在前一个请求完成时请求每个页面。

你可以这样做:

function loadData(url, pages, cb) {
    const urls = [];

    for (let i = 1; i <= pages; i++) {
        urls.push(`${url}/?page=${i}`);
    }

    return Promise.all(urls.map(url => fetch(url).then(response => response.json())))
        .then(responses => {
            var results = responses.reduce((accum, response) => [...accum, ...response.results], []);
            cb(results);
            return results;
        });
}

【讨论】:

    猜你喜欢
    • 2018-08-14
    • 2020-10-01
    • 2016-05-10
    • 1970-01-01
    • 2016-12-13
    • 2019-03-17
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    相关资源
    最近更新 更多