为啥 subscribe() 不起作用但模板中的异步可以?
Posted
技术标签:
【中文标题】为啥 subscribe() 不起作用但模板中的异步可以?【英文标题】:Why does subscribe() not working but aync in template does?为什么 subscribe() 不起作用但模板中的异步可以? 【发布时间】:2019-08-13 07:28:18 【问题描述】:有一个套接字服务可以在应用程序之间发送和接收消息。我可以发送消息,也可以使用getMessages | async
在模板中接收这些消息。但是当我尝试在我的组件中用getMessages().subscribe(...)
替换getMessages | async
时,它不再起作用了。那么我做错了什么?
这是组件代码:
@Component(
selector: 'showTemplate',
template: `<ng-container #dynamicTemplate>
<div class="mx-auto m-5"
[innerhtml]="content"
">
</div>
<!-- WORKS
<div *ngFor="let x of showContent() | async">
x | json --
</div>
-->
</ng-container>`,
providers: [ SocketService ]
)
export class ShowTemplateComponent implements OnInit
@Input() data:any;
constructor(
private socketService: SocketService,
)
ngOnInit()
this.socketService.connect();
// doesn't work
this.socketService.getMessages().subscribe(response =>
console.log("------", response)
)
/**
*
*
*/
public showContent()
return this.socketService.getMessages();
服务如下所示:
import Injectable from "@angular/core";
import Observable, of, Subject from 'rxjs';
import WebSocketSubject from 'rxjs/observable/dom/WebSocketSubject';
import environment from '@app/../environments/environment';
import Message from "../model/message";
import Status from "../model/status";
@Injectable()
export class SocketService
public serverMessages = new Array<Message>();
private socket$: WebSocketSubject<Message>;
private status: Status;
private connected: Status;
private decoderSettings;
/**
*
*/
constructor(
private authenticationService: AuthenticationService,
)
console.log("SOCKET SERVICE INIT")
// get logged user
this.decoderSettings = this.authenticationService.decoderSettings;
this.connect();
public connect(): void
const CONTENT_SERVER_URL = 'wss://' + this.decoderSettings.ipAddress + ':9041';
this.socket$ = new WebSocketSubject(
url: CONTENT_SERVER_URL,
openObserver:
next: value =>
console.log("OPEN", value);
this.status = Status.CONNECTED;
,
closeObserver:
next: value =>
console.log("CLOSEING", value);
this.status = Status.DISCONNECTING;
);
this.socket$
.subscribe(
(message) =>
console.log('SEND', message);
this.serverMessages.push(message);
,
(err) =>
this.status = Status.ERROR;
console.error(err);
,
() =>
console.warn('CLOSED!');
this.status = Status.DISCONNECTED;
);
public disconnect(): void
this.socket$.unsubscribe();
public send(message: Message): void
console.log("send: ", message)
this.socket$.next(message);
public getMessages():Observable<any>
console.log("getMessages: ", this.serverMessages)
return of(this.serverMessages);
我希望这只是一个简单的错误,但经过长时间的搜索后我真的找不到它。非常感谢您的帮助!
【问题讨论】:
定义“不再起作用” @JamieRees 很好,我希望在this.socketService.getMessages().subscribe(...)
中看到任何新收到的消息。但这里没有显示任何内容。模板中带有<div *ngFor="let x of showContent() | async">
的代码向我显示任何新消息
订阅时,您是否从订阅中获取价值?例如subscribe(message => this.messages = message);
?
@JamieRees subscribe()
的内部部分只被调用一次。然后是向我显示一个空数组console.log(response)
。所以答案是,是的。但它只显示一次,任何进一步的消息都会被忽略。
【参考方案1】:
在
public getMessages():Observable<any>
console.log("getMessages: ", this.serverMessages)
return of(this.serverMessages);
您正在创建一个 Observable,它发出您传递给它的值 (this.serverMessages
),然后完成。您应该创建一个 BehaviourSubject 而不是 serverMessages
数组。然后,您应该告诉 BehaviourSubject 发出一个新值,而不是推送到 Array。 https://www.learnrxjs.io/subjects/behaviorsubject.html
【讨论】:
我也试过BehaviourSubject
,但它也不起作用【参考方案2】:
我相信它可以工作,因为在 html 中,每当重新渲染视图时,您都会重新订阅,触发对 getMessages() 的新调用,创建一个新的 Observable 以返回。
虽然在代码中您只订阅了一次,但我可能错了,但您返回 Observable 的模式似乎是错误的,因为仅向您的数组添加内容不会触发对先前返回的 Observable 的更新。
编辑:如果您在服务的 getMessages() 方法中设置断点,您会获得多少次命中?如果我是正确的,如果您专注于视图,那么您应该每秒获得几次点击。
【讨论】:
【参考方案3】:不出所料-我的大脑被炸了。这解决了我的问题:
public getMessages():Observable<any>
return this.socket$;
【讨论】:
以上是关于为啥 subscribe() 不起作用但模板中的异步可以?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 WCF 休息服务(不是使用 WCF 休息服务模板创建的)不起作用?