Angular でwebsocket を利用する(rxjs/webSocket)

はじめに

Angular でwebsocket を利用する方法をまとめます。
rxjs のSubject を利用したAngular + RxJS + WebSocket で チャットアプリを作る – Subject 利用サンプル という記事がありますが、今回は rxjs/webSocket を利用しています。

angular websocket chat
angular websocket chat

rxjs/webSocket

Angular から利用しているため、個別の installは必要ありません。

Angular webSocket service

Angularの serviceとして以下のような MessageEventを返す serve()を作ります。
deserializer を指定しないと思うように messageを受信できませんでした。

rxjs/webSocketのDocument によると deserializer, the default for this property is JSON.parse とあるので MessageEventを parseするような動きになるようです。
深く考えず Exampleにあるように deserializerを指定してしまいました。

import { webSocket, WebSocketSubject } from 'rxjs/webSocket';

@Injectable({
  providedIn: 'root'
})
export class ChatService {

  constructor() { }

  serve(): WebSocketSubject<MessageEvent> {
    return webSocket({
      url: `ws://localhost:8080/ws`,
      deserializer: message => {
        return message;
      }
    });
  }

Angular webSocket component

Angularの componentとして以下のように subscribe() しています。
MessageEvent として受け取り JSON.parse(message.data)とすることで実際のユーザーメッセージが受信できます。

また、errorの typeを今回は明示的に websocketが closeされた場合と、そうでない場合で処理をしています。

import { WebSocketSubject } from 'rxjs/webSocket';

export class ChatRoomComponent implements OnInit {
  subject: WebSocketSubject<unknown>;

  ngOnInit() {
    this.subject = this.chatService.serve();
    this.subject.subscribe(
      (message: MessageEvent) => {
        this.message = JSON.parse(message.data) as ChatMessage;
      }, (err) => {
        if (err.type === 'error' ) {
          this.router.navigate(['/chattop']);
        }
        if (err.type === 'close' ) {
          this.router.navigate(['/chattop']);
        }
      }, () => {
        console.log('complete');
      }
    );
  }
}

また、以下の stackoverflowで例示されている通り this.subject.retry().subscribe(...) とすることで websocketの再接続が可能となるようです。

Angular webSocket template

html側からは以下のように {{ message }} で送ってきたデータと送ったデータを表示することができます。

<div>{{ message }}</div>

まとめ

Angular でwebsocket を利用することができました。
rxjs/Subject と比べて細かいところが指定できなかったりするんだろうなぁと思ってましたが、再接続やエラー処理がそれなりにできそうな感じでした。