используйте fetch для рекурсивной загрузки страниц - PullRequest
0 голосов
/ 08 марта 2020

Я хотел бы получить данные из этого API: "https://swapi.co/api/planets". Данные разбиваются на страницы, как https://swapi.co/api/planets/?page=1, https://swapi.co/api/planets/?page=2 ....

Я хочу создать API, который принимает URL, страницу и обратный вызов в качестве аргументов , Он будет извлекать все данные постранично, пока не достигнет страницы, указанной в аргументах.

Например,

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

Это загрузит данные со страницы 1, страницы 2, страницы 3, страницы 4 и страницы 5.

Вот моя попытка, однако она не работает. Может кто-нибудь указать мне правильное направление?

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?

Ответы [ 2 ]

1 голос
/ 08 марта 2020

Как было сказано ранее, вам, вероятно, не нужно ждать каждого вызова до конца sh, прежде чем делать следующий, но если вы действительно хотите, я просто должен сказать, что мне гораздо проще разобрать (как человек) с использованием asyn c / await.

Я сделал быструю базовую c версию здесь, в этом фрагменте, чтобы вы могли ее увидеть, без обработки ошибок или проверки правильности данных. Может быть, этот подход может подойти вам лучше?

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);
0 голосов
/ 08 марта 2020

Поскольку каждый запрос не зависит от предыдущего, я бы использовал метод 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;
        });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...