RxJ允许前n个请求然后延迟

时间:2017-08-09 14:04:35

标签: javascript typescript rxjs observable

我想使用RxJs从具有n接口的服务请求Observable条记录。该服务具有DDoS保护机制,因此如果我立即请求1000条记录,我将被阻止几分钟。

我在每条记录上放置了1秒的静态延迟,如下所示:

    Observable.from(users.map((x, i) => ({unwrap: x, index: i}) ))
      .concatMap(i => Observable.of(i).delay(1000))
      .combineLatest(tokenObs)
      .flatMap(res => {
        let [val, token] = res;
        return this.userByIdentifierService.getUserByIdentifier(token, val.unwrap.user.Id)
          .flatMap(user => this.shipByUserService.getShipByUser(user.user))
          .map(ship => ({index: val.index, ship: ship}));
      })
      .do(res => this.users[res.index].ship = res.ship)

我想加快用户界面的感知速度。

我想知道是否有一种优雅的方式来获取第一个,即没有任何等待时间的10条记录,然后只添加超过该数字的记录的延迟?

所以预期的行为是: 前10条记录=> 10记录后没有延迟=>

之间延迟1秒

通过Angular使用带有RxJS的打字稿。

3 个答案:

答案 0 :(得分:2)

这对你有用......

Observable
  .from(users.map((x, i) => ({unwrap: x, index: i}) ))
  .concatMap(i => i.index < 10 ? i : Observable.of(i).delay(1000))
;

答案 1 :(得分:0)

我个人会使用下划线限制功能来实现此功能以及请求计数器,以确定是否应使用限制调用或非限制调用。 像下面这样的东西应该让你开始。

 const throttled = _.throttle(this.userByIdentifierService.getUserByIdentifier, 1000);
 let firstCall = true;
 Observable.from(users.map((x, i) => ({unwrap: x, index: i}) ))
   .concatMap(i => Observable.of(i).delay(1000))
   .combineLatest(tokenObs)
   .flatMap(res => {
      let [val, token] = res;
      if(firstCall){
        return this.userByIdentifierService.getUserByIdentifier(token, val.unwrap.user.Id)
         .flatMap(user => this.shipByUserService.getShipByUser(user.user))
        .map(ship => ({index: val.index, ship: ship}));
       } else {
       throttled(token, val.unwrap.user.id).flatMap(user => this.shipByUserService.getShipByUser(user.user)).map(ship => ({index: val.index, ship}));
       }
    })
  .do(res => this.users[res.index].ship = res.ship)

详细了解油门方法 - Underscore docs

答案 2 :(得分:0)

如果索引数据,@ Hitit的解决方案会更好。这是我提出的适用于非索引数据的解决方案。

Observable.from(users.map((x, i) => ({unwrap: x, index: i}) ))
  //.concatMap(i => Observable.of(i).delay(1000))
  .let(j => j.take(10).concat(
            j.skip(10).concatMap(i => Observable.of(i).delay(1000))))
  .do(s => console.log('fetching', s.index))

稍后我也会发现你可以使用线性增加的延迟来解决这个问题,即

 .concatMap(i => Observable.of(i).delay(Math.min(50 + i.index * 25, 1000)))