我正在尝试连续执行一些可观察性,这与concatMap一样,但是我希望它们只能执行一次,即使我有多个订阅者,我也尝试了share和shareReplay运算符,但没有一个似乎有效。
代码如下:
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<any> {
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
中找到我的样本结果是:
Start refresh access token
Start refresh access token
Start connect
Start connect
Start authent
Start authent
Tap
Finished 1
Tap
Finished 2
但是我要寻找的是:
Start refresh access token
Start connect
Start authent
Tap
Finished 1
Finished 2
也许这已经被回答了,但是我看不到我所缺少的,如果有人可以提供帮助,那就太好了。
编辑:
我会解释我的需求,也许我以错误的方式解决了这个问题。 我正在编写包装socket.io客户端的服务类,该类中每个发出或侦听socket.io事件的函数都必须检查我们是否已连接并验证到socket.io。
在每个订阅上,多个可观察对象需要执行以下操作:
在这一系列可观察对象中,第一个订户将执行所有可观察对象,如果第二个订户在观察对象正在执行中等待相同结果时到达,则不要两次发起连接。
如果在连接完成后到达第三位或更多位,我们仍然需要检查变量isAuthenticated是否已更改,如果为false,则像第一个订阅者一样操作,如果为true,则继续。
希望它有助于阐明我在寻找什么。
答案 0 :(得分:1)
您希望将数据分配给一个可观察对象,然后订阅该可观察对象,而不是调用initFunction()
,后者创建的可观察对象与订阅者一样多。但是通过将数据分配给可观察的数据并进行订阅,可以防止这种情况的发生,也可以使用shareReplay
:
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)