RXJS – `switchMap` 操作符中用于首次或后续执行的条件

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

RXJS - Conditional in switchMap operator for first or subsequent execution

问题

我的服务中的http fetch方法有一个名为"showLoadingSpinner"的参数。当它被设置为false时,HttpContext的DISABLE_LOADER_FOR_REQUEST将被设置为true。

我希望为每个后续调用设置showLoadingSpinner为false,但不适用于第一个调用:

第一次调用:显示加载符号
下一次调用:不显示加载符号

现在我需要在组件方法的管道内部有一个条件,用于判断是否是第一个服务调用,而不需要创建额外的状态变量。

我不想要的方式:

isFirstCall = true;

fetchData(): Observable {
return this.reload$.pipe(
switchMap(() => this.service.fetch(this.isFirstCall),
tap(() => this.isFirstCall = false)
);
}

我想要的方式:

fetchData(): Observable {
return this.reload$.pipe(
switchMap(() => this.service.fetch(<这里应该基于RXJS操作符的条件,判断是否是第一次发射>))
);
}

是否有来自RXJS的操作符可以用于此目的?

英文:

My http fetch method in the service has a parameter "showLoadingSpinner". When it's set to false, the HttpContext DISABLE_LOADER_FOR_REQUEST = true will be set.

I want to set the showLoadingSpinner to false for every subsequent call but not for the first one:

First Call: show Loading Spinner
Next Calls: Don&#39;t show the Loading Spinner

Now I need a conditional inside the pipe in my components method, if it's the first service call or not, without creating a additional state variable.

What I don't want to have:

isFirstCall = true;

fetchData(): Observable&lt;Bla&gt; {
    return this.reload$.pipe(
        switchMap(() =&gt; this.service.fetch(this.isFirstCall),
        tap(() =&gt; this.isFirstCall = false)
    );
}

What I want to have:

fetchData(): Observable&lt;Bla&gt; {
    return this.reload$.pipe(
        switchMap(() =&gt; this.service.fetch(&lt;here should be a conditional based on a RXJS operator, if it&#39;s the first emission or not&gt;)
    );
}

Is there an operator from RXJS which I can use for it?

答案1

得分: 4

你可以使用 switchMap rxjs 操作符的索引来判断是否是第一次发射。

fetchData(): Observable<Bla> {
    return this.reload$.pipe(
        switchMap((_, index) => this.service.fetch(index))
    );
}
英文:

You could use the index of switchMap rxjs operator to know if it is the first emission or not.

fetchData(): Observable&lt;Bla&gt; {
    return this.reload$.pipe(
        switchMap((_, index) =&gt; this.service.fetch(index)
    );
}

答案2

得分: 0

我看到了@tlvi38的答案,虽然从技术上讲它能够工作,但也意味着:

  • 你将永远不会关闭流
  • 你将一直检查从1到无穷大是否有东西等于0,这并不是最优的方法

另一种方法是只获取重新加载可观察对象的第一个发射并进行一次获取,然后关闭流。

如果你想要这样做,这是它的实现方式:

fetchData(): Observable&lt;Bla&gt; {
    return this.reload$.pipe(
        first(),
        switchMap(() =&gt; this.service.fetch())
    );
}
英文:

I see @tlvi38's answer and while it'll technically work, it also means that:

  • You'll never close the stream
  • You'll keep checking from 1 to infinity if something is equal to 0, which is not optimal

Another approach would be to get only the first emission of the reload observable and fetch once. Then close the stream.

If you wish to do that instead, here's how it'd look like:

fetchData(): Observable&lt;Bla&gt; {
    return this.reload$.pipe(
        first(),
        switchMap(() =&gt; this.service.fetch())
    );
}

huangapple
  • 本文由 发表于 2023年6月29日 15:13:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76578794.html
匿名

发表评论

匿名网友

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

确定