Angular 8 - 从两个不同的组件订阅一项服务
Angular 8 - subscribe to one service from two different components
我有一个 angular 服务和两个使用此服务的不同的不相关组件:
服务代码:
const url = 'ws://localhost:8080
@Injectable({
provideIn: 'root',
})
export class MyService{
public subject: Subject<Status>;
constructor(wsService: WebSocketService){
this.subject = <Subject<Status>>wsService.connect(url).map(
(response: MessageEvent): Status => {
let data = JSON.parse(response.data);
return data;
}
);
}
getObs(){
return this.subject.asObservable();
}
sendMsg(msg){
this.subject.next(msg);
}
}
组件 1:
@Component
.. some irrelevant code ..
constructor(private service: MyService){
this.service.getObs().subscribe( data =>
console.log('comp1');
);
console.log('comp1 - after subscribe');
}
.. some irrelevant code ..
组件 2:
@Component
.. some irrelevant code ..
constructor(private service: MyService){
this.service.getObs().subscribe( data =>
console.log('comp2');
);
console.log('comp2 - after subscribe');
}
.. some irrelevant code ..
我在控制台中得到以下输出:
comp1
comp1 - 订阅后
comp2 - 订阅后
我认为我应该得到的输出:
comp1
comp1 - 订阅后
comp2
comp2 - 订阅后
谁能解释一下问题出在哪里?
注意:我将我的服务添加到模块提供程序并得到了相同的结果。
谢谢。
这是 webSocketService 的代码:https://github.com/elliotforbes/ng-chat/blob/master/src/app/common/services/websocket.service.ts
您可以使用行为主题而不是普通主题。
您应该控制自己的主题,而不是依靠 WebSocketService.connect
并假设您将获得所需的行为。
从您发布的link到WebSocketService
的源代码,我们看到它是一个普通的主题。 ReplaySubject
.
提供了您想要的功能——在订阅时发出一个值(假设存在)
您应该声明一个本地 ReplaySubject
,这是您的组件将订阅的内容。然后您将订阅您的 WebSocketService
。来自 WebSocketService
的任何回复都将映射到一个状态,然后发送到您的本地主题。
const url = 'ws://localhost:8080
@Injectable({
provideIn: 'root',
})
export class MyService{
// Declare local ReplaySubject that emits the last value upon subscription
private subject: Subject<Status> = new ReplaySubject<Status>(1);
constructor(wsService: WebSocketService) {
// Subscribe to the web socket service.
// Subscribing in constructors is fairly bad practice,
// although you can get away with it in singleton services
wsService.connect(url).pipe(
// map responses to statuses
map((response: MessageEvent): Status => {
let data = JSON.parse(response.data);
return data;
})
).subscribe((status: Status) => {
// send the status to all subscribers
this.subject.next(status);
});
}
getObs(): Observable<Status> {
return this.subject.asObservable();
}
sendMsg(msg): void {
this.subject.next(msg);
}
}
我有一个 angular 服务和两个使用此服务的不同的不相关组件:
服务代码:
const url = 'ws://localhost:8080
@Injectable({
provideIn: 'root',
})
export class MyService{
public subject: Subject<Status>;
constructor(wsService: WebSocketService){
this.subject = <Subject<Status>>wsService.connect(url).map(
(response: MessageEvent): Status => {
let data = JSON.parse(response.data);
return data;
}
);
}
getObs(){
return this.subject.asObservable();
}
sendMsg(msg){
this.subject.next(msg);
}
}
组件 1:
@Component
.. some irrelevant code ..
constructor(private service: MyService){
this.service.getObs().subscribe( data =>
console.log('comp1');
);
console.log('comp1 - after subscribe');
}
.. some irrelevant code ..
组件 2:
@Component
.. some irrelevant code ..
constructor(private service: MyService){
this.service.getObs().subscribe( data =>
console.log('comp2');
);
console.log('comp2 - after subscribe');
}
.. some irrelevant code ..
我在控制台中得到以下输出:
comp1
comp1 - 订阅后
comp2 - 订阅后
我认为我应该得到的输出:
comp1
comp1 - 订阅后
comp2
comp2 - 订阅后
谁能解释一下问题出在哪里?
注意:我将我的服务添加到模块提供程序并得到了相同的结果。
谢谢。
这是 webSocketService 的代码:https://github.com/elliotforbes/ng-chat/blob/master/src/app/common/services/websocket.service.ts
您可以使用行为主题而不是普通主题。
您应该控制自己的主题,而不是依靠 WebSocketService.connect
并假设您将获得所需的行为。
从您发布的link到WebSocketService
的源代码,我们看到它是一个普通的主题。 ReplaySubject
.
您应该声明一个本地 ReplaySubject
,这是您的组件将订阅的内容。然后您将订阅您的 WebSocketService
。来自 WebSocketService
的任何回复都将映射到一个状态,然后发送到您的本地主题。
const url = 'ws://localhost:8080
@Injectable({
provideIn: 'root',
})
export class MyService{
// Declare local ReplaySubject that emits the last value upon subscription
private subject: Subject<Status> = new ReplaySubject<Status>(1);
constructor(wsService: WebSocketService) {
// Subscribe to the web socket service.
// Subscribing in constructors is fairly bad practice,
// although you can get away with it in singleton services
wsService.connect(url).pipe(
// map responses to statuses
map((response: MessageEvent): Status => {
let data = JSON.parse(response.data);
return data;
})
).subscribe((status: Status) => {
// send the status to all subscribers
this.subject.next(status);
});
}
getObs(): Observable<Status> {
return this.subject.asObservable();
}
sendMsg(msg): void {
this.subject.next(msg);
}
}