タイトルのことがやりたかっただけなんですけど。
Mattermostに投稿があった時に、Angularでもその内容をリアルタイムで表示したくてですね。APIに定期的にアクセスしてもいいんですけど、せっかくなのでWebSocketで接続したい。
というわけで、"Angular WebSocket"あたりで検索してみたところ、Socket.IOを使うだのObserverやら使うだの、かなり難度の高い方法ばかりでてくるんですが……
最終的に、下記のコードだけで実現できました。
app.component.ts
import { Component, OnInit } from '@angular/core';
import { webSocket } from "rxjs/webSocket";
const subject = webSocket('wss://mattermost-server/api/v4/websocket');
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor() { }
ngOnInit() {
subject.subscribe(
(message: any) => {
if(message.event == 'posted') console.log(JSON.parse(message.data.post).message);
},
err => console.log(err),
() => console.log('complete')
);
}
}
んもー、すごく簡単じゃないですか。いやー、RxJS便利。
ここにたどり着くまでにあれこれ遠回りしましたよ。
ちなみに、素のJavaScriptだとこんな感じ。
const socket = new WebSocket("wss://mattermost-server/api/v4/websocket");
socket.addEventListener("message", event => {
let message = JSON.parse(event.data);
if(message.event == 'posted') console.log(JSON.parse(message.data.post).message);
});
そう、こんな風にシンプルに書きたかったんですよ。んもー。
追記。サービス化するとこんな感じ。
websocket.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { webSocket } from "rxjs/webSocket";
const subject = webSocket('wss://mattermost-server/api/v4/websocket');
@Injectable({
providedIn: 'root'
})
export class WebsocketService {
data = new Subject<any>();
data$= this.data.asObservable();
constructor() {
subject.subscribe(
(message: any) => {
this.data.next(message);
},
err => console.log(err),
() => console.log('complete')
);
}
}
app.component.ts
import { Component, OnInit } from '@angular/core';
import { WebsocketService } from './websocket.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(
private websocket: WebsocketService,
) {}
ngOnInit() {
this.websocket.data$.subscribe(
(message: any) => {
if(message.event == 'posted') console.log(JSON.parse(message.data.post).message);
}
);
}
}
サービス側で、イベント種別毎だとかチャンネル毎だとかで分けてnext
に流すと便利なんだろうな……
気が向いたら実装してみよう。