是不是可以编写一个rxjs操作符来控制对它的源的订阅?

huangapple go评论51阅读模式
英文:

Is it possible to write an rxjs operator that controls subscription to it's source?

问题

让我们假设我有一个名为 source 的可观察对象,它具有以下属性:

  • 第一次订阅时,它会发出网络请求
  • 它是幂等的,因此在第一次订阅后,它总是发出相同的值
  • 它的优先级较低,因此我们不希望过于急切地订阅它

理想情况下,如果有一种名为 delaySubscriptionUntil 的操作符,它可以延迟订阅,直到另一个可观察对象 s 发出一个值。

例如:

const s = new Subject<void>();
const l = source
  .pipe(
    delaySubscriptionUntil(s));

l.subscribe(console.log);
// 上面的代码不会输出任何内容,直到执行下面这行代码
s.next();

我查看了文档以查找是否存在这样的现有操作符,但没有找到。

英文:

Let's say I have an observable source that has the following properties:

  • It makes a network request the first time it's subscribed to

  • It's idempotent, so it will always emit the same value after it's first subscribed to

  • It's low priority, so we don6t6 want to be too eager in subscribing to it

What would be ideal is if there were some sort of operator delaySubscriptionUntil that would delay subscription until some other observable s emits a value.

So for example:

const s = new Subject&lt;void&gt;();
const l = source
  .pipe(
    delaySubscriptionUntil(s));

l.subscribe(console.log);
// The above won&#39;t print anything until this line executes
s.next();

I looked through the documentation to see if there's an existing operator like this, but haven't found one.

答案1

得分: 1

以下是您要翻译的内容:

You just put the subject first and switchMap

只需将主题放在前面并使用 switchMap

const l = s.pipe(
switchMap(() => source)
);

一旦主题发出,源将被订阅。

一旦主题发出,源将被订阅。

Any thing that is after wont work as it relies on the previous observable emitting a value. You can have a filter in the chain that stops the previous observable's emission being emitted but there is nothing you can pass back up the chain to control outer subscriptions.

任何在之后的部分都不会起作用,因为它依赖于前一个可观察对象发出一个值。您可以在链中添加一个过滤器,以阻止前一个可观察对象的发射,但没有办法将控制外部订阅的信息传递回链中。

You could use a takeWhile

您可以使用 takeWhile

let allow = false;

const l = source.pipe(
takeWhile(allow)
);

但在这里,对源的订阅仍然处于活动状态,它正在发出值,只是被阻止传递。

So you could make a similar operator that keeps an internal flag and is flipped by a subject but source is still going to be emitting, you are just filtering values. You could buffer up the values if you don't want to lose them.

因此,您可以创建一个类似的操作符,它保留内部标志,并由主题翻转,但源仍然会发出值,您只是在筛选值。如果您不想丢失这些值,您可以将它们缓冲起来。

英文:

You just put the subject first and switchMap

const l = s.pipe(
  switchMap(() =&gt; source)
);

Once the subject emits then the source will be subscribed to.

Any thing that is after wont work as it relies on the previous observable emitting a value. You can have a filter in the chain that stops the previous observable's emission being emitted but there is nothing you can pass back up the chain to control outer subscriptions.

You could use a takeWhile

let allow = false;

const l = source.pipe(
  takeWhile(allow)
);

but here the subscription to source is active, it is emitting values, they are just stopped from being passed through.

So you could make a similar operator that keeps an internal flag and is flipped by a subject but source is still going to be emitting, you are just filtering values. You could buffer up the values if you don't want to lose them.

答案2

得分: 0

你可以使用 share(),它将共享它之前发生的任何结果,直到你使用新的 URL 调用 sub.next(),然后请求将再次发生。

const sub = new BehaviorSubject<string>('http://example.com/api');
const result$ = sub.pipe(
  exhaustMap(url => this.http.get(url)),
  share()
)

// 这些订阅中的每一个都会共享结果。
// HTTP 请求将仅调用一次,
// 直到你向 BehaviorSubject 发送新的 URL。
result$.subscribe(val => console.log(val));
result$.subscribe(val => console.log(val));
result$.subscribe(val => console.log(val));
result$.subscribe(val => console.log(val));
英文:

You could use share() which will share the result of anything that happened before it until you call sub.next() with a new url then the request will happen again.

const sub = new BehaviorSubject&lt;string&gt;(&#39;http://example.com/api&#39;);
const result$ = sub.pipe(
  exhaustMap(url =&gt; this.http.get(url)),
  share()
)

// Each one of these subscriptions will share the result.
// The http request will be called only once
// until you send a new url to the BehaviorSubject.
result$.subscribe(val =&gt; console.log(val));
result$.subscribe(val =&gt; console.log(val));
result$.subscribe(val =&gt; console.log(val));
result$.subscribe(val =&gt; console.log(val));

huangapple
  • 本文由 发表于 2023年2月7日 04:43:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75366387.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定