【问题标题】:How to get more API records when the response size is limited响应大小受限时如何获取更多 API 记录
【发布时间】:2023-03-03 00:15:01
【问题描述】:

我对 React 或 JavaScript 没有太多经验。我正在创建一个从 API 获取时间序列数据的简单应用程序。数据用于绘制折线图(React Apex Chart)。都很好。

问题在于 API 响应大小被限制为最多 2,000 条记录,有时我们需要更多数据。

API 文档说:

响应大小限制为最多 2,000 条记录。如果必须返回更多记录,则响应标头包含一个带有 URI 的 Link 标头以获取下一组记录:

链接:https://apiurl; rel="下一个"

我的获取码:

我的代码获取 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">

我知道解决方案可能是某种分页,但我不完全理解这个概念。我已经搜索了类似的问题,但没有运气。

希望有人可以为我提供帮助、提示或代码。

【问题讨论】:

    标签: javascript reactjs api fetch


    【解决方案1】:

    谢谢大家。我得到了这两种答案的混合使用。

    我不知道这是一个好方法还是“正确”的方法。也许你们可以给我一些反馈?

    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))
    }
    

    【讨论】:

      【解决方案2】:

      如果我正确理解了这个问题,我会在您的 FetchApi 函数中添加一个变量,以便它可以查询您的初始 API URL 或后续页面的 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 秒,您可以在函数再次调用自身之前添加延迟,但显然这会影响检索所有数据的总时间。

      【讨论】:

      • 请注意,文档说响应将包含下一页数据的完整 URL。没有理由像您在此处那样构建此 URL。
      • 比较 == true 是多余的。
      • 技术上是的,但它是一个示例来说明逻辑而不是要使用的实际代码,我认为声明 ==true 会增加清晰度。
      • 我发布了一些有用的东西。两种答案的混合。也许你可以看看它?
      • 很高兴听到您已经成功了!该函数的迭代方面对我来说看起来不错。是否成功返回超过一页的结果,然后在全部检索完毕后停止?
      【解决方案3】:

      我不知道您使用的是什么 API,但听起来您需要做的就是从标头中获取下一组结果的 URL,然后向它发出请求。

      在返回response.json() 之前,您可以使用response.headers.get() 访问标头。因此,您可以执行let nextPage = response.headers.get('Link') 之类的操作来获取完整的链接标头作为字符串。然后你可以在分号处拆分它,并将第一部分用作下一个分页请求的 URL。

      【讨论】:

      • 请注意,解析 Link 标头比仅拆分分号更复杂。
      • 是吗?根据问题中提到的回复,似乎nextPage = nextPage.split(';'); nextPage.pop(); nextPage = nextPage.join(';') 应该可以解决问题?
      • 根据 OP,Link 标头以字母“link”开头,然后是制表符和尖括号。这些对 URL 无效。 (还有,为什么要打电话给pop()join()?)
      • 也许我看错了;我认为这只是表明 Link 标头具有键名 link ,然后箭头指向该值,即 URL 后跟 ; rel="next" 。你可能是对的,这有点不清楚。
      • 好的。我明白你的意思了。如果该解释是正确的(正如您所说的还不清楚),那么仍然需要处理尖括号。不管这些细节如何,解析 Link 标头才是正确的做法。
      猜你喜欢
      • 1970-01-01
      • 2011-07-06
      • 2020-09-27
      • 2020-01-23
      • 1970-01-01
      • 2019-02-26
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多