我如何使用RxJ来阻止任何AJAX调用请求,直到前一个调用结束

Moe*_*eri 7 javascript throttling reactive-programming rxjs

我有一个observable,它代表一个由一些外部组件触发的动作.出于这个问题的目的,我们称之为createBananaAction.我有一个bananaService方法create执行一个AJAX请求并返回创建的香蕉作为Promise.

因此,每当有一些数据从createBananaAction我们到达时,我们都想打电话bananaService.create().

代码如下所示:(使用RxJs)

this.createdBananas = createBananaAction.flatMap(() => bananaService.create());
Run Code Online (Sandbox Code Playgroud)

现在,挑战是"限制"createBananaAction,以便它只能在收到前一个香蕉后请求另一个香蕉.简单地说:永远不会有两个同时来电bananaService.create().请注意,我不想及时限制,而是在bananaService执行其操作时忽略所有传入的新香蕉请求.

我做了一些研究,找到了看似合适的pausable操作员.

我的代码现在看起来像这样:

const pausableCreateBananaAction = createBananaAction.pausable();

this.createdBananas = pausableCreateBananaAction
    .do(() => pausableCreateBananaAction.pause())
    .flatMap(() => bananaService.create())
    .do(() => pausableCreateBananaAction.resume());
Run Code Online (Sandbox Code Playgroud)

这似乎有效,但我不喜欢我需要这些do语句来手动触发pauseresume语句的事实.

我发现,你可以通过一个可观察到pausable那么应该产生falsetrue在适当的时间,但是这也需要我在受到手动推值.像这样的东西:

const letItGoThrough = new Rx.Subject();

this.createdBananas = createBananaAction
    .pausable(letItGoThrough.startWith(true))
    .do(() => letItGoThrough.onNext(false))
    .flatMap(() => bananaService.create())
    .do(() => letItGoThrough.onNext(true));
Run Code Online (Sandbox Code Playgroud)

所以现在我有了一个Rx.Subject(主题就像是RxJs的训练轮,你使用的是直到你在RxJs上经验不足而你不再需要它们.)和两次调用do.

是否有完全"反应"的方式做我想要的?或者我是否坚持使用这种结构,看起来和我的口味有点过于迫切.

先感谢您.

Bra*_*don 7

只需使用flatMapFirst而不是flatMap:

this.createdBananas = createBananaAction.flatMapFirst(() => bananaService.create());
Run Code Online (Sandbox Code Playgroud)

以上假设您的bananaService.create()回报是冷可观察的.如果它返回一个hot observable或a Promise,那么我们需要包含调用Observable.defer以将其转换为cold observable,以便flatMapFirst可以正确控制其触发:

this.createdBananas = createBananaAction
    .flatMapFirst(() => Rx.Observable.defer(() => bananaService.create()));
Run Code Online (Sandbox Code Playgroud)

  • 从RxJS5开始,`flatMapFirst`被称为`exhaustMap`. (5认同)