concatMap and share to play a series fo observables only once even if multiple subscribers
我正在尝试连续执行一些可观察性,这与concatMap一样,但是我希望它们只能执行一次,即使我有多个订阅者,我也尝试了share和shareReplay运算符,但它们似乎都不起作用。
这是代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import { EMPTY, Observable, BehaviorSubject, of, from, concat, timer } from 'rxjs'; import { concatMap, map, switchMap, tap, filter, take, share, shareReplay, exhaust, publishLast, refCount } from 'rxjs/operators'; const refreshAccessToken = () => { console.log("Start refresh access token") return timer(2000); } const connect = () => { console.log("Start connect") return timer(3000) } const authent = () => { console.log("Start authent") return timer(2000) } let isAuthenticated = false; let isExpired = true; function initSocket(): Observable { if (!isAuthenticated) { let observable$ = of(1); if (isExpired) { observable$ = refreshAccessToken(); } return observable$.pipe( concatMap(() => connect()), concatMap(() => authent()), tap(() => { isAuthenticated = true; console.log("Tap") }), share() ); } return of(1); } initSocket().subscribe(() => console.log("Finished 1")) initSocket().subscribe(() => console.log("Finished 2")) |
您可以在https://stackblitz.com/edit/rxjs-4memxw?embed=1&file=index.ts中找到我的示例
结果是:
1 2 3 4 5 6 7 8 9 10 | Start refresh access token Start refresh access token Start connect Start connect Start authent Start authent Tap Finished 1 Tap Finished 2 |
但是我正在寻找的是:
1 2 3 4 5 6 | Start refresh access token Start connect Start authent Tap Finished 1 Finished 2 |
也许已经回答了,但是我看不到我所缺少的,如果有人可以帮助,那就太好了。
编辑:
我会解释我的需求,也许我以错误的方式解决了这个问题。
我正在编码一个包装一个socket.io客户端的服务类,该类中每个发出或侦听socket.io事件的函数都必须检查我们是否已连接并通过socket.io进行身份验证。
在每个订阅上,多个可观察对象都需要执行以下操作:
有效,如果是,请转到4
在这一系列的可观察对象中,第一个用户将执行所有可观察对象,如果第二个用户在观察对象正在执行时到达等待相同的结果,则不要两次发起连接。
如果在连接完成后到达第三位或更多位,我们仍然需要检查变量isAuthenticated是否已更改,如果为false,则像第一个订阅者一样操作,如果为true,则继续。
希望它有助于阐明我在寻找什么。
您可能希望将数据分配给一个可观察对象,然后订阅该可观察对象,而不是调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | let obs$ = new Observable(); function initSocket(): void { if (!isAuthenticated) { let observable$ = of(1); if (isExpired) { observable$ = refreshAccessToken(); } obs$ = observable$.pipe( concatMap(() => connect()), concatMap(() => authent()), tap(() => { isAuthenticated = true; console.log("Tap") }), shareReplay() ); } } initSocket(); obs$.subscribe(() => console.log("Finished 1")) obs$.subscribe(() => console.log("Finished 2")) setTimeout(() => { obs$.subscribe(() => console.log("Finished 3 after 20 seconds")) }, 20000) |
叠砖