我如何使用 RxJs 推迟对 AJAX 调用的任何请求,直到前一个调用解决
How can I use RxJs to hold off any requests for an AJAX call until the previous one resolves
我有一个 observable 表示由某些外部组件触发的操作。为了这个问题的目的,我们称它为createBananaAction
。
我有一个 bananaService
方法 create
执行 AJAX 请求和 returns 创建的香蕉作为 Promise
.
所以,每当一些数据从 createBananaAction
到达时,我们要调用 bananaService.create()
。
代码如下所示:(使用 RxJs)
this.createdBananas = createBananaAction.flatMap(() => bananaService.create());
现在,挑战是 "throttle" createBananaAction,以便它只能在收到前一个香蕉后请求另一个香蕉。简而言之:永远不会有两个同时调用 bananaService.create()
。
请注意,我不想及时限制,而是在 bananaService 执行其操作时忽略所有传入的新香蕉请求。
我做了一些研究,找到了看似合适的 pausable
运算符。
我的代码现在看起来像这样:
const pausableCreateBananaAction = createBananaAction.pausable();
this.createdBananas = pausableCreateBananaAction
.do(() => pausableCreateBananaAction.pause())
.flatMap(() => bananaService.create())
.do(() => pausableCreateBananaAction.resume());
这似乎可行,但我不喜欢这样的事实,即我需要这些 do
语句来手动触发 pause
和 resume
语句。
我发现你可以将一个 observable 传递给 pausable
,它应该会在适当的时候产生 false
或 true
,但这也需要我手动推送一个主题中的值.像这样:
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
.
是否有完全 "Reactive" 的方式来做我想做的事?或者我是否坚持这种看起来和感觉上对我的口味来说有点过于迫切的结构。
提前谢谢你。
只需使用 flatMapFirst 而不是 flatMap
:
this.createdBananas = createBananaAction.flatMapFirst(() => bananaService.create());
以上假定您的 bananaService.create()
returns 是一个冷的可观察对象。如果它 returns 是一个热 observable 或 Promise
,那么我们需要用 Observable.defer
包装调用以将其转换为冷 observable 以便 flatMapFirst
可以正确控制它的触发:
this.createdBananas = createBananaAction
.flatMapFirst(() => Rx.Observable.defer(() => bananaService.create()));
我有一个 observable 表示由某些外部组件触发的操作。为了这个问题的目的,我们称它为createBananaAction
。
我有一个 bananaService
方法 create
执行 AJAX 请求和 returns 创建的香蕉作为 Promise
.
所以,每当一些数据从 createBananaAction
到达时,我们要调用 bananaService.create()
。
代码如下所示:(使用 RxJs)
this.createdBananas = createBananaAction.flatMap(() => bananaService.create());
现在,挑战是 "throttle" createBananaAction,以便它只能在收到前一个香蕉后请求另一个香蕉。简而言之:永远不会有两个同时调用 bananaService.create()
。
请注意,我不想及时限制,而是在 bananaService 执行其操作时忽略所有传入的新香蕉请求。
我做了一些研究,找到了看似合适的 pausable
运算符。
我的代码现在看起来像这样:
const pausableCreateBananaAction = createBananaAction.pausable();
this.createdBananas = pausableCreateBananaAction
.do(() => pausableCreateBananaAction.pause())
.flatMap(() => bananaService.create())
.do(() => pausableCreateBananaAction.resume());
这似乎可行,但我不喜欢这样的事实,即我需要这些 do
语句来手动触发 pause
和 resume
语句。
我发现你可以将一个 observable 传递给 pausable
,它应该会在适当的时候产生 false
或 true
,但这也需要我手动推送一个主题中的值.像这样:
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
.
是否有完全 "Reactive" 的方式来做我想做的事?或者我是否坚持这种看起来和感觉上对我的口味来说有点过于迫切的结构。
提前谢谢你。
只需使用 flatMapFirst 而不是 flatMap
:
this.createdBananas = createBananaAction.flatMapFirst(() => bananaService.create());
以上假定您的 bananaService.create()
returns 是一个冷的可观察对象。如果它 returns 是一个热 observable 或 Promise
,那么我们需要用 Observable.defer
包装调用以将其转换为冷 observable 以便 flatMapFirst
可以正确控制它的触发:
this.createdBananas = createBananaAction
.flatMapFirst(() => Rx.Observable.defer(() => bananaService.create()));