我试图找出RxJ。特别是ShareReplay运算符。根据我的理解,如果对一个可观察对象有两个订阅,那么该可观察对象应该执行两次。除非涉及到shareReplay。显然我的理解是错误的,因为这不是我在这里发生的事情。有人可以帮我理解吗?
export class TestComponent implements OnInit {
constructor() {}
i = 0;
ngOnInit() {
console.clear();
let ob = this.httpcall().pipe(map(d => d));
let ob1$ = ob.pipe(map(d => d.toUpperCase()));
let ob2$ = ob.pipe(map(d => d.toLowerCase()));
ob1$.subscribe(d => {
console.log(d);
});
ob2$.subscribe(d => {
console.log(d);
});
}
httpcall() {
console.log("called");
this.i++;
return of("server cAlled:" + this.i);
}
}
输出:
called
SERVER CALLED:1
server called:1
即使有两个订阅并且不涉及shareReplay,我的计数器也没有增加到两个。
我期望(没有shareReplay):
called
SERVER CALLED:1
called
server called:2
并且我期望使用let ob = this.httpcall().pipe(map(d=>d),shareReplay());
:
called
SERVER CALLED:1
server called:1
答案 0 :(得分:2)
当您调用订阅时,这将导致可观察对象执行其定义要执行的所有操作。它是使用of("server cAlled: 1");
定义的,然后将其传递给地图运算符。因此,由于您订阅了两次,因此of
会做两次,而map
会做两次。
您碰巧在名为httpcall的函数中创建了可观察对象,但是该可观察对象对httpcall一无所知。 httpcall将不会再被调用。
如果您希望this.i的增量成为预订时发生的事情的一部分,则可能需要使用Observable.create。例如:
httpcall() {
return Observable.create((observer) => {
this.i++;
observer.next("server called: " + this.i);
observer.complete();
})
}
答案 1 :(得分:0)
似乎return observable是它自己的,所以它的主体不会被执行两次,因此我重新创建了示例以显示正常observable和of之间的区别
export class AppComponent implements OnInit {
constructor(
) {
}
i = 0;
ngOnInit() {
console.clear();
const ob = this.httpCall1();
const ob1$ = ob.pipe(map(d => d.toUpperCase()));
const ob2$ = ob.pipe(map(d => d.toLowerCase()));
ob1$.subscribe(d => {
console.log(d);
});
ob2$.subscribe(d => {
console.log(d);
});
this.i = 0;
const ob2 = this.httpCall2();
const ob3$ = ob2.pipe(map(d => d.toUpperCase()));
const ob4$ = ob2.pipe(map(d => d.toLowerCase()));
ob3$.subscribe(d => {
console.log(d);
});
ob4$.subscribe(d => {
console.log(d);
});
}
httpCall1() {
return of('server1 called:' + ++this.i).pipe(
tap(d => console.log('tap1', d)),
);
}
httpCall2() {
return new Observable<string>((observer) => {
this.i++;
observer.next('server2 called: ' + this.i);
observer.complete();
}).pipe(
tap(d => console.log('tap2', d)),
);
}
}
答案 2 :(得分:0)
这是因为httpcall()
仅通过以下行let ob = this.httpcall().pipe(map(d => d));
被调用一次。因此,这意味着Observable
返回的httpcall()
随后将被重用。
如果可以的话,现在考虑一下ob
,它是源可观察的。如果您订阅此Observable,您将获得of("server cAlled:" + this.i);
,其中this.i = 1
。如果再次执行方法this.i
,httpcall()
只会增加,但不会。 相反,您正在订购冷的Observable ob
,它将仅打印用于创建它的内容。 this.i
的值(等于1)已经存储在Observable内部ob
,并且无论您订阅ob
有多少次,在创建新实例之前都不会更改它。
现在让我们看一下下面的不同代码:
let ob1$ = this.httpcall().pipe(map(d => d)).pipe(map(d => d.toUpperCase()));
let ob2$ = this.httpcall().pipe(map(d => d)).pipe(map(d => d.toLowerCase()));
在这种情况下,httpcall()
被两次调用,因此this.i++;
将会发生两次,并且您将获得想要的结果。