为什么Observable.delay()不受尊重?

时间:2017-12-01 18:05:51

标签: angular rxjs ngrx

我有一个简单的HTTP调用:

  getContributors(pageNumber): Observable<any> {
    const url = `${this.apiBaseUrl}/orgs/angular/public_members?&page=${pageNumber}`;
    const requestOptions = this.getRequestOptions();

    return this.http.get(url, requestOptions);
  }

通过ngrx effect进行通话。

...
return this.contributorsService.getContributors(payload.pageNumber)
        .delay(new Date(Date.now() + Math.random() * 500))
        ... // mergeMap etc. here

但是,当HTTP调用返回多个值的数组时,它们 一次性一次

我是否误解了delay()运营商的目的(在这种情况下,我如何达到预期的结果?)或者我是以错误的方式使用它?

注意:我导入了扩充import 'rxjs/add/operator/delay';

更新:澄清一下,预期结果是:我希望拆分数组,并在给定的数组中单独发出数组中的每个值(常量) )时间

更新2 :所以,数组实际拆分

 .flatMap(data => Observable.from(data))

事实上,如果

 .do(value => console.log(value))

每个值都单独打印

但是,如果不是.do(....)

我把

.delay(3000)
.do(() => console.log(new Date())

我可以看到延迟没有得到尊重完全(除了它实际上等待3000发出所有的序列,没有延迟 - 连续,即多个console.logs)

2 个答案:

答案 0 :(得分:3)

好的,所以关于可观察流中的数组的事情是,它们就像流中的任何其他单个值一样。您的http调用返回一个数组值,因此它将整个数组作为单个值返回,该值一次完成。如果你想将一个数组拆分成多个值,你当然可以这样做,但你需要告诉rxjs这样做,我首选的方法是使用flatMap,如下所示:

.flatMap(arrVal => Observable.from(arrVal))

此操作会将您的数组值展平为可观察的值流,因此您可以像这样使用它:

return this.contributorsService.getContributors(payload.pageNumber)
    .flatMap(data => Observable.from(data))
    .delay(Math.random() * 500) // you should just feed a ms value to delay if you want constant time interval, date parameters mean delay till that date, so they'll all just flow through at that date

然而,上述工作不会起作用,因为延迟会将整个流程按时间而不是每个项目进行移动,因此要完成展平和分离,我们需要更加明确,从这个答案中得出: Separate observable values by specific amount of time in RxJS

return this.contributorsService.getContributors(payload.pageNumber)
           .switchMap(data => Observable.interval(Math.random() * 500)
                                        .take(data.length)
                                        .map(i => data[i]))

这样我们以均匀间隔的间隔手动压平阵列。

此版本也可以使用,可能会感觉更清洁:

return this.contributorsService.getContributors(payload.pageNumber)
           .flatMap(data => Observable.from(data))
           .zip(Observable.interval(Math.random() * 500), (d,i) => d)

这只是使用zip运算符将每个项目压缩为一个间隔发出的observable。

现在,您应该以恒定的间隔一次看到每个数组项目所需的行为。但是,如果您正在使用http服务,则可能需要在响应上调用.json()以将值作为数组获取,如下所示:

return this.http.get(url, requestOptions).map(res => res.json());

答案 1 :(得分:2)

您可以再次使用flatMap' delay()

return this.contributorsService.getContributors(payload.pageNumber)
  .flatMap(x => x)                                            // to single values
  .flatMap(x => Observable.of(x).delay(Math.random() * 500))  // apply delay

const Observable = Rx.Observable

Observable.of([1,2,3])
  .flatMap(x => x)
  .flatMap(x => Observable.of(x).delay(Math.random() * 500))
  .subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.3/Rx.js"></script>