为什么subscribe()不起作用,但模板中的aync起作用?

时间:2019-08-13 07:28:18

标签: angular websocket rxjs

有一个套接字服务,可以在应用程序之间发送和接收消息。我可以使用getMessages | async发送消息,也可以在模板中接收这些消息。但是,当我尝试在组件中将getMessages | async替换为getMessages().subscribe(...)时,它将不再起作用。那我做错了吗?

这是组件代码:

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

我希望这只是一个简单的错误,但是经过漫长的搜索,我真的无法找到它。因此,谢谢您的帮助!

3 个答案:

答案 0 :(得分:1)

public getMessages():Observable<any> {
            console.log("getMessages: ", this.serverMessages)
            return of(this.serverMessages);
        }

您正在创建一个Observable,它发出传递给它的值(this.serverMessages)然后完成。您应该创建一个BehaviourSubject而不是serverMessages数组。然后,不要推送到Array,而应通知BehaviourSubject发出新值。 https://www.learnrxjs.io/subjects/behaviorsubject.html

答案 1 :(得分:0)

我相信它是可行的,因为在html中,只要重新渲染视图,您就需要重新订阅,从而触发对getMessages()的新调用,并创建一个新的Observable来返回。

虽然在代码中您只订阅一次,但是我可能错了,但是似乎您返回了Observable的模式错误,因为仅向数组添加内容不会触发对先前返回的Observable的更新。

编辑:如果您在服务的getMessages()方法中设置了一个断点,那么您会被击中几次?如果我的观点是正确的,那么如果您专注于视图,那么应该会每秒获得几次点击。

答案 2 :(得分:0)

不出所料-我的大脑被炸了。这解决了我的问题:

- job_name: 'kubernetes-pods'
  kubernetes_sd_configs:
  - role: pod