如何使用 angular2 限制每秒 API 调用

Mos*_*she 6 rest angular-services angular

我的 API 限制为每秒 10 次调用(但每天数千次),但是,当我运行此函数时(调用对象的每个样式 ID,> 每秒 10 次):

  getStyleByID(styleID: number): void {
    this._EdmundsAPIService.getStyleByID(styleID).subscribe(
      style => {this.style.push(style); },
      error =>  this.errorMessage = <any>error);
  }
Run Code Online (Sandbox Code Playgroud)

从这个函数(只有 1 次调用,使用 onInit):

  getStylesWithoutYear(): void {
    this._EdmundsAPIService.getStylesWithoutYear(this.makeNiceName, this.modelNiceName, this.modelCategory)
      .subscribe(
        styles => { this.styles = styles;
                      this.styles.years.forEach(year =>
                        year.styles.forEach(style =>
                          this.getStyleByID(style.id)));

        console.log(this.styles); },
        error =>  this.errorMessage = <any>error);
  }
Run Code Online (Sandbox Code Playgroud)

它每秒进行 > 10 个呼叫。如何限制或减慢这些调用以防止出现 403 错误?

Ang*_*hef 2

我有一个非常简洁的解决方案,您可以将两个可观察量.zip() 运算符结合起来:

  1. 发出请求的可观察对象。
  2. 另一个 observable 每 0.1 秒发出一个值。

最终,您每 0.1 秒就会发出一个可观察到的请求(= 每秒 10 个请求)。

这是代码(JSBin):

// Stream of style ids you need to request (this will be throttled).
const styleIdsObs = new Rx.Subject<number>();

// Getting a style means pushing a new styleId to the stream of style ids.
const getStyleByID = (id) => styleIdsObs.next(id);

// This second observable will act as the "throttler".
// It emits one value every .1 second, so 10 values per second.
const intervalObs = Rx.Observable.interval(100);

Rx.Observable
  // Combine the 2 observables. The obs now emits a styleId every .1s. 
  .zip(styleIdsObs, intervalObs, (styleId, i) => styleId)
  // Get the style, i.e. run the request.
  .mergeMap(styleId => this._EdmundsAPIService.getStyleByID(styleId))
  // Use the style.
  .subscribe(style => {
    console.log(style);
    this.style.push(style);
  });

// Launch of bunch of requests at once, they'll be throttled automatically.
for (let i=0; i<20; i++) {
  getStyleByID(i);
}
Run Code Online (Sandbox Code Playgroud)

希望您能够将我的代码转换为您自己的用例。如果您有任何疑问,请告诉我。

更新:感谢 Adam,还有一个JSBin展示了如何在请求不一致时限制请求(请参阅评论中的 convo)。它使用concatMap()运算符而不是zip()运算符。