Как получить больше записей API, когда размер ответа ограничен - PullRequest
1 голос
/ 16 апреля 2019

У меня нет большого опыта работы с React или JavaScript. Я создаю простое приложение, которое извлекает данные временных рядов из API. Данные используются для построения линейного графика (React Apex Chart). Все хорошо.

Проблема в том, что размер ответа API ограничен максимум 2000 записями, а иногда нам нужно больше данных.

Документация API гласит:

Размер ответа ограничен максимум 2000 записями. Если необходимо вернуть больше записей, заголовок ответа содержит заголовок Link с URI для получения следующего набора записей:

Ссылка: https://apiurl; rel = "next"

Мой код извлечения:

Мой код выбирает данные API, сортирует их и отправляет их дочернему компоненту (диаграмма).

  FetchAPI(){
    fetch(https://MYURLHERE?from=FROMDATE&to=TODATE)
      .then(response => response.json())
      .then(data => this.setState({ 
        kWhData: data.map((kWh) => kWh._kWh),
        TimeStampData: data.map((time) => time._time),
        loading: false
      }))
      .catch(error => console.log('Fetching failed', error))
  }
Link header: link →<https://MYURLHERE?from=FROMDATE&limit=2000&to=TODATE>; rel="next">

Я знаю, что решением может быть какая-то нумерация страниц, но я не совсем понимаю эту концепцию. Я искал похожие проблемы без удачи.

Надеюсь, кто-нибудь может дать мне руку помощи, подсказки или код.

Ответы [ 3 ]

2 голосов
/ 16 апреля 2019

Если я правильно понял вопрос, я бы добавил переменную в вашу функцию FetchApi, чтобы она могла запрашивать либо ваш начальный URL-адрес API, либо URL-адрес для следующей страницы:

FetchAPI(requestURL){
    // Fetch function here
}

Идея состоит в том, что эта функция может затем вызывать себя итеративно, с URL-адресом следующей страницы результатов, передаваемой в качестве параметра для каждого вызова, до тех пор, пока ответ не покажет все данные, которые были получены.

Таким образом, ваш начальный вызов будет FetchAPI ('https://MYURLHERE? From = FROMDATE & to = TODATE ').

Затем можно добавить строку для повторного вызова этой функции, если достигнут предел скорости. Например:

FetchAPI(requestURL){
    fetch(requestURL)
        .then(response => {
            if(response.dataLimit == true){ // Or however this is expressed
                // Concat new data with any already retrieved
                this.FetchAPI(nextPageUrl) // Get the URL of the next page and call FetchAPI again with this e.g https://MYURLHERE?from=FROMDATE&limit=2000&to=TODATE
            } else {
                // Otherwise stop and do something else now that you have a complete set of data
            }
        })
}

Стоит сказать, что это непроверенный код, но, надеюсь, достаточно для прояснения принципа.

Также, если API имеет ограничение скорости запросов, например 1 секунду, вы можете добавить задержку, прежде чем функция снова вызовет себя, хотя, очевидно, это повлияет на общее время получения всех данных.

2 голосов
/ 16 апреля 2019

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

Перед возвратом response.json() вы можете получить доступ к заголовкам с помощью response.headers.get(). Таким образом, вы можете сделать что-то вроде let nextPage = response.headers.get('Link'), чтобы получить полный заголовок Link в виде строки. Затем вы можете разделить его точкой с запятой и использовать первую часть в качестве URL для следующего разбитого на страницы запроса.

0 голосов
/ 17 апреля 2019

Спасибо всем.Я получил его для работы с сочетанием обоих ответов.

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

setTimeout был только для тестирования, но я думаю, что мне нужно иметь минимум 1000?

Учетные данные / заголовок необходимы для получения API.

FetchAPI(requestURL) {
    fetch(requestURL, {
        credentials: 'include',
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json",
                "x-xsrf-token": this.myXRSFToken,
                "origin": `${window.location.protocol}//${window.location.host}`
            }
        })
    .then(response => {
        let Responseheader = response.headers.get('Link')
        response.json()
        .then(data => this.setState({
            TestData: this.state.TestData.concat(data)
        }))
        if (Responseheader){
            let nextPageUrl = Responseheader.match(/\bhttps?:\/\/\S+Z/gi)
            setTimeout(() => {
                this.FetchAPI(nextPageUrl)
            }, 2000);
        } else {
            console.log('Done fetching API')
            this.setState({ 
                loading: false
            })
            return
          }  
    })
    .catch(error => console.log('Fetching failed', error))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...