【问题标题】:Ionic limit API calls离子限制 API 调用
【发布时间】:2019-01-25 11:19:25
【问题描述】:

我使用第三方库在 Ionic 中使用 Spotify 的 API(我没有直接从我的代码中进行 HTTP 查询),并且我试图限制每秒发送的请求数。

我的期望:

  • 我可以为每个请求设置延迟
  • 或设置每秒允许的最大请求数,当我需要发送超过每秒允许的最大请求数(这将是我设置的数字)时,这段代码(库、我的代码等)将排队请求并稍后发送。

我不是 Ionic 方面的专家,也不是 Angular 方面的专家。 我试过这个:

const apiCalls = [];

//in a for loop
apiCalls.push(fromPromise(this.spotifyApi.getArtistRelatedArtists(sourceArtist.mbid)).delay(this.apiDelay).toPromise());

//then
concat(...apiCalls).subscribe(

好像没什么效果,比如我发了20个请求,apiDelay为1秒,不到2秒就全部完成了。

我尝试使用库,比如这个: simple-rate-limiter 但它们应该与 'require' 一起使用,Ionic 抱怨说:

找不到模块的声明文件

如何在 Ionic 中延迟对外部 API 的请求?

【问题讨论】:

  • 请求是否排队或被丢弃?
  • 请求应该排队。基本上,如果我需要进行 10 次 API 调用,而 API 每秒只允许我进行 5 次调用,那么与此任务相关的 Promise 应在至少 2 秒后返回。
  • 如果您有 10 个客户端同时使用您的应用,如何为每个客户端设置限制?
  • API 限制通常针对每个客户端。我只对限制当前客户端的吞吐量感兴趣。

标签: angular api ionic-framework limit


【解决方案1】:

或许你可以试试下面这个简单的方法,demo https://stackblitz.com/edit/angular-http-client-kfnniw

// mock some random requests
for (let i = 0; i < 10; i++) {
  setTimeout(() => this.httpCalls.push({
    id: i,
    request: this.http.get<any[]>(this.apiUrl)
  }), Math.random() * 5000);
}

// handle queue
let interval = setInterval(() => {
  let toRun = this.httpCalls.splice(0, 5);
  for (let i = 0; i < toRun.length; i++) {
    ((r) => {
      let s = new Subject();
      r.request.subscribe(s);
      this.httpResponses.push({ id: r.id, subject: s });
    })(toRun[i]);
  }
}, 1000);

// in some other places, process actual requests
setInterval(() => {
  let r = this.httpResponses.splice(0, this.httpResponses.length);
  for (let i = 0; i < r.length; i++) {
    r[i].subject.subscribe(data => {
      console.log(`finished request ${r[i].id}`);
    });
  }
}, 1000);

【讨论】:

  • 抱歉,正如我提到的,我的 API 调用不是 HTTP 调用。我在 Spotify 上使用了一个包装库,它在内部进行 HTTP 调用。我需要延迟对 API 的调用,并且非常重要的是,保持答案的顺序(为什么我使用 concat 命令)。对于 HTTP,我过去在 RxJS 中使用了“延迟”方法,它似乎工作正常。
  • @Anakin001,我上面展示的只是一个简单的队列任务和处理它们的实现,正如你从演示中看到的那样,我什至根本没有使用http。所以你可以调整它并使用 concatMap 或类似的东西来满足你自己的需要。
  • 老实说,我想我了解您在示例中所做的大部分工作,但我不知道如何使其适应我的用例(我是 Angular 的初学者) .另外,我不认为我想添加这种异步处理,因为在我的情况下,我从一开始就知道我需要执行的 API 调用的数量(setInterval 听起来像是我将用于连续处理的东西)。我希望能够为 RxJS 的 concat 提供一个参数,以便它延迟执行每个任务。老实说,我不明白为什么我在 for 循环中的代码在 push 时不能完成这项工作。
  • 经过一些测试,我得出的结论是,在我的示例中,只有输出延迟了所有推送承诺的给定数量,延迟不会按顺序应用。
  • 哦,我刚刚意识到您可能只是在处理一个非常简单的用例,即为您提供了一组已修复的请求,对吧?如果是这种情况,您可以简单地将它们分组并根据组索引延迟它们。
【解决方案2】:

我通过将代码更改为类似这样的方式解决了这个问题。 它基本上使用 setTimeout 来延迟 API 调用的开始。

const apiCalls = [];
let i = 0;

//in a for loop
apiCalls.push(this.getRelatedArtistsWithDelay(i * this.apiDelay, sourceArtist.id[this.PROVIDER]));
i++;

//then
concat(...apiCalls).subscribe(

//and the getRelatedArtistsWithDelay function calls the API with a delayed start
  private getRelatedArtistsWithDelay(delay, artistId){
    return new Promise(resolve => {
      setTimeout(() => {
        this.spotifyApi.getArtistRelatedArtists(artistId).then((data) => {
          resolve(data);
        })
      },
      delay)
    });
  }

【讨论】:

    猜你喜欢
    • 2017-06-17
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多