Angular 8-从两个不同组件订阅一个服务

Angular 8-从两个不同组件订阅一个服务,angular,service,components,observable,subject,Angular,Service,Components,Observable,Subject,我有一个角度服务和两个不同的不相关组件使用此服务: 服务代码: const url = 'ws://localhost:8080 @Injectable({ provideIn: 'root', }) export class MyService{ public subject: Subject<Status>; constructor(wsService: WebSocketService){ this.subject = <Subject<

我有一个角度服务和两个不同的不相关组件使用此服务:

服务代码:

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);
  }

}
构成部分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的代码:

您可以使用行为主题而不是普通主题


您可以使用行为主语而不是普通主语


你应该控制自己的主题,而不是依赖
WebSocketService.connect
并假设你将获得所需的行为

从您发布的
WebSocketService
源代码的链接中,我们可以看到它是一个简单的主题。您想要的功能—在订阅时发出值(如果存在值)—由
ReplaySubject
提供

您应该声明一个本地
ReplaySubject
,这是您的组件将订阅的。然后您将订阅您的
WebSocketService
。来自
WebSocketService
的任何响应都将映射到一个状态,然后发送到您的本地主题

consturl='ws://localhost:8080
@注射的({
provideIn:'根',
})
导出类MyService{
//声明在订阅时发出最后一个值的本地ReplaySubject
私有主题:主题=新的ReplaySubject(1);
构造函数(wsService:WebSocketService){
//订阅web套接字服务。
//订阅构造函数是相当糟糕的做法,
//虽然你可以在单例服务中侥幸逃脱
wsService.connect(url.pipe)(
//将响应映射到状态
映射((响应:MessageEvent):状态=>{
让data=JSON.parse(response.data);
返回数据;
})
).订阅((状态:status)=>{
//将状态发送给所有订阅者
本.主题.下一个(状态);
});
}
getObs():可观察{
返回此.subject.asObservable();
}
sendMsg(msg):无效{
this.subject.next(msg);
}
}

你应该控制自己的主题,而不是依靠
WebSocketService.connect
并假设你将获得所需的行为

从您发布的
WebSocketService
源代码的链接中,我们可以看到它是一个简单的主题。您想要的功能—在订阅时发出值(如果存在值)—由
ReplaySubject
提供

您应该声明一个本地
ReplaySubject
,这是您的组件将订阅的。然后您将订阅您的
WebSocketService
。来自
WebSocketService
的任何响应都将映射到一个状态,然后发送到您的本地主题

consturl='ws://localhost:8080
@注射的({
provideIn:'根',
})
导出类MyService{
//声明在订阅时发出最后一个值的本地ReplaySubject
私有主题:主题=新的ReplaySubject(1);
构造函数(wsService:WebSocketService){
//订阅web套接字服务。
//订阅构造函数是相当糟糕的做法,
//虽然你可以在单例服务中侥幸逃脱
wsService.connect(url.pipe)(
//将响应映射到状态
映射((响应:MessageEvent):状态=>{
让data=JSON.parse(response.data);
返回数据;
})
).订阅((状态:status)=>{
//将状态发送给所有订阅者
本.主题.下一个(状态);
});
}
getObs():可观察{
返回此.subject.asObservable();
}
sendMsg(msg):无效{
this.subject.next(msg);
}
}

wsService.connect(url)return是什么数据类型?
WebSocketService
是您创建的吗?MyService没有任何明显的重播行为,组件2是否在触发组件1输出的消息后开始订阅?下面是webSocketService的代码:
wsService.connect(url)
返回什么数据类型?并且
webSocketService
是您创建的吗?MyService没有任何明显的重播行为,组件2是否在触发组件1输出的消息后开始订阅?下面是webSocketService的代码:我们不知道正在使用什么类型的主题-它只是被转换到一个
主题
-这并不意味着它实际上是一个正常的
主题
。我们需要更多关于代码的信息。有关主题的详细信息。这肯定不是一个行为主体。您可以使用下面的行为主题私有类别:BehaviorSubject=新的BehaviorSubject({})`我很清楚不同类型的主题。OP显然需要一个
ReplaySubject
,因为没有初始状态。但是我们不知道wsService.connect(url)返回什么,所以任何答案都只是猜测。我们不知道正在使用什么类型的主题-它只是被转换到一个
主题
-这并不意味着它实际上是一个正常的
主题
。我们需要更多关于代码的信息。有关主题的详细信息。这肯定不是一个行为主体。您可以使用下面的行为主题私有类别:BehaviorSubject=新的BehaviorSubject({})`我很清楚不同类型的主题。OP显然需要一个
ReplaySubject
,因为没有初始状态。但是我们不知道wsService.connect(url)返回什么,所以有什么答案吗
@Component

.. some irrelevant code ..

constructor(private service: MyService){
  this.service.getObs().subscribe( data => 
    console.log('comp2');
  );

  console.log('comp2 - after subscribe');
}

.. some irrelevant code ..