两个组件如何订阅同一个事件?
How can two Components subscribe to the same Event?
我有一个 Client 服务,其数组 "messages" 包含服务器消息。然后我有一个订阅该数组的组件,并检查每条新消息的主题。
像这样:
client.messages.subscribe(msg => {
switch (msg.SUBJECT)
{
case 'SOME_TEXT':
//some code;
break;
default:
console.log(msg);
break;
}
});
然而,当我使用相同的代码将第二个组件订阅到该数组时 (唯一的区别是开关中的主题),仅执行第一个组件的开关。
第二个组件永远不会收到消息。
代码应该是正确的。该消息仅由项目树中第一个组件接收。
正如您请求的 ClientService 代码,这里是:
import { Injectable } from '@angular/core';
import { WebsocketService } from './websocket.service';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
const CHAT_URL = //MY IP AND PORT;
export interface Message {
SUBJECT: string;
NAME?: string;
ROOMS?: string[];
//plus many others, some are strings, some numbers
}
@Injectable()
export class ClientService {
public messages: Subject < Message > ;
constructor(wsService: WebsocketService) {
this.messages = < Subject < Message >> wsService
.connect(CHAT_URL).pipe(
map((response: MessageEvent): Message => {
console.log(response);
const data = JSON.parse(response.data);
return data;
}));
}
这是我在上面使用的 WebSocketService。
import { Injectable } from '@angular/core';
import { Observable, Subject, Observer } from 'rxjs';
@Injectable()
export class WebsocketService {
constructor() {}
private subject: Subject < MessageEvent > ;
public connect(url): Subject < MessageEvent > {
if (!this.subject) {
this.subject = this.create(url);
console.log('Successfully connected: ' + url);
}
return this.subject;
}
private create(url): Subject < MessageEvent > {
const ws = new WebSocket(url);
const observable = Observable.create(
(obs: Observer < MessageEvent > ) => {
ws.onmessage = obs.next.bind(obs);
ws.onerror = obs.error.bind(obs);
ws.onclose = obs.complete.bind(obs);
return ws.close.bind(ws);
});
const observer = {
next: (data: Object) => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
}
}
};
return Subject.create(observer, observable);
}
}
向 ClientService 添加一个 share() 运算符,看看它是否有效
this.messages = < Subject < Message >> wsService
.connect(CHAT_URL).pipe(
map((response: MessageEvent): Message => {
console.log(response);
const data = JSON.parse(response.data);
return data;
}),share());
我有一个 Client 服务,其数组 "messages" 包含服务器消息。然后我有一个订阅该数组的组件,并检查每条新消息的主题。
像这样:
client.messages.subscribe(msg => {
switch (msg.SUBJECT)
{
case 'SOME_TEXT':
//some code;
break;
default:
console.log(msg);
break;
}
});
然而,当我使用相同的代码将第二个组件订阅到该数组时 (唯一的区别是开关中的主题),仅执行第一个组件的开关。
第二个组件永远不会收到消息。
代码应该是正确的。该消息仅由项目树中第一个组件接收。
正如您请求的 ClientService 代码,这里是:
import { Injectable } from '@angular/core';
import { WebsocketService } from './websocket.service';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
const CHAT_URL = //MY IP AND PORT;
export interface Message {
SUBJECT: string;
NAME?: string;
ROOMS?: string[];
//plus many others, some are strings, some numbers
}
@Injectable()
export class ClientService {
public messages: Subject < Message > ;
constructor(wsService: WebsocketService) {
this.messages = < Subject < Message >> wsService
.connect(CHAT_URL).pipe(
map((response: MessageEvent): Message => {
console.log(response);
const data = JSON.parse(response.data);
return data;
}));
}
这是我在上面使用的 WebSocketService。
import { Injectable } from '@angular/core';
import { Observable, Subject, Observer } from 'rxjs';
@Injectable()
export class WebsocketService {
constructor() {}
private subject: Subject < MessageEvent > ;
public connect(url): Subject < MessageEvent > {
if (!this.subject) {
this.subject = this.create(url);
console.log('Successfully connected: ' + url);
}
return this.subject;
}
private create(url): Subject < MessageEvent > {
const ws = new WebSocket(url);
const observable = Observable.create(
(obs: Observer < MessageEvent > ) => {
ws.onmessage = obs.next.bind(obs);
ws.onerror = obs.error.bind(obs);
ws.onclose = obs.complete.bind(obs);
return ws.close.bind(ws);
});
const observer = {
next: (data: Object) => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
}
}
};
return Subject.create(observer, observable);
}
}
向 ClientService 添加一个 share() 运算符,看看它是否有效
this.messages = < Subject < Message >> wsService
.connect(CHAT_URL).pipe(
map((response: MessageEvent): Message => {
console.log(response);
const data = JSON.parse(response.data);
return data;
}),share());