如何使用 RxJs 推迟对 AJAX 调用的任何请求,直到前一个请求解决 [英] How can I use RxJs to hold off any requests for an AJAX call until the previous one resolves

查看:20
本文介绍了如何使用 RxJs 推迟对 AJAX 调用的任何请求,直到前一个请求解决的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 observable,它表示由某个外部组件触发的操作.出于这个问题的目的,我们将其称为 createBananaAction.我有一个带有方法 createbananaService 执行 AJAX 请求并将创建的香蕉作为 Promise 返回.

I have an observable that represents an action that is triggered by some outside component. For the purpose of this question, let's call it createBananaAction. I have a bananaService with a method create that performs an AJAX request and returns the created banana as a Promise.

因此,每当有数据从 createBananaAction 到达时,我们都想调用 bananaService.create().

So, whenever some data arrives from the createBananaAction, we want to call bananaService.create().

代码如下:(使用RxJs)

this.createdBananas = createBananaAction.flatMap(() => bananaService.create());

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

Now, the challenge is to "throttle" the createBananaAction so that it can only request another banana after it received its previous one. Simply put: there can never be two simultaneous calls to bananaService.create(). Note that I do not want to throttle in time, but rather ignore all incoming requests for a new banana while the bananaService is doing its thing.

我做了一些研究,发现了看似合适的pausable 运算符.

I did some research and found the seemingly appropriate pausable operator.

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

My code now looks like this:

const pausableCreateBananaAction = createBananaAction.pausable();

this.createdBananas = pausableCreateBananaAction
    .do(() => pausableCreateBananaAction.pause())
    .flatMap(() => bananaService.create())
    .do(() => pausableCreateBananaAction.resume());

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

This seems to work, but I don't like the fact that I need these do statements to manually trigger the pause and resume statements.

我发现你可以将一个 observable 传递给 pausable ,然后它应该在适当的时候产生 falsetrue ,但这也需要我手动推送主题中的值.像这样:

I found out you can pass an observable into pausable which should then produce false or true at appropriate times, but this also requires me to manually push values in a subject. Something like this:

const letItGoThrough = new Rx.Subject();

this.createdBananas = createBananaAction
    .pausable(letItGoThrough.startWith(true))
    .do(() => letItGoThrough.onNext(false))
    .flatMap(() => bananaService.create())
    .do(() => letItGoThrough.onNext(true));

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

So now I have an Rx.Subject (subjects are like training wheels for RxJs, it's what you use until you become experienced enough at RxJs that you no longer need them.) and two calls to do.

是否有一种完全反应式"的方式来做我想做的事?或者我是否坚持使用这种外观和感觉对我的口味来说有点过于必要的结构.

Is there a fully "Reactive" way of doing what I want? Or am I stuck with this construct that looks and feels a bit too imperative for my tastes.

先谢谢你.

推荐答案

只需使用 flatMapFirst 而不是 flatMap:

Just use flatMapFirst instead of flatMap:

this.createdBananas = createBananaAction.flatMapFirst(() => bananaService.create());

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

The above assumes your bananaService.create() returns a cold observable. If it returns a hot observable or a Promise, then we need to wrap the call with Observable.defer to convert it to a cold observable so that flatMapFirst can control its firing properly:

this.createdBananas = createBananaAction
    .flatMapFirst(() => Rx.Observable.defer(() => bananaService.create()));

这篇关于如何使用 RxJs 推迟对 AJAX 调用的任何请求,直到前一个请求解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆