TL; DR
- RxJSの
rxjs/webSocket
はメッセージ送受信時にデフォルトでJSON.parse
/JSON.stringify
を実行します。 - 単純なテキストを受信する場合は、オプションの
serializer
またはdeserializer
を指定すれば良いです。
遭遇した事象
AngularからWebSocketサーバと通信する場合は、RxJSのrxjs/webSocket
を使用すれば簡単に実現できます。たとえばWebSocketでメッセージを受信するServiceクラスは以下のように数行で書けます。便利ですね。
サンプルコード
import { Injectable } from '@angular/core'; import { Subject } from "rxjs"; import { webSocket } from "rxjs/webSocket"; @Injectable({ providedIn: 'root' }) export class MessageService { connect(): Subject<string> { return webSocket({ url: "ws://127.0.0.1:8000/", }); } }
しかし、サーバからシンプルなテキスト(たとえば "first message"とか)を受け取るとパースできない...これが今回解決したいことです。
SyntaxError: Unexpected token i in JSON at position 1
解決策
rxjs/webSocket
のオプションを定義する WebSocketSubjectConfigを参照すると、ちゃんと書いてありました。たとえば deserializer
には以下のような説明があります。(サンプルもあった)
deserializer: A deserializer used for messages arriving on the socket from the server. Defaults to JSON.parse. サーバーから受信するメッセージをデシリアライズする時に使われる関数。デフォルトは JSON.parse です。
渡ってきたテキストをそのまま呼び出し元に返すようにオプション serializer / deserializer にカスタム関数を定義すればOKです。
サンプルコード
import { Injectable } from '@angular/core'; import { Subject } from "rxjs"; import { webSocket } from "rxjs/webSocket"; @Injectable({ providedIn: 'root' }) export class MessageService { connect(): Subject<string> { return webSocket({ url: "ws://127.0.0.1:8000/", deserializer: ({ data }) => data // ここでカスタムのdeserializer関数を渡す }); } }
参考
サンプル実装をGitHubに置きました。
困ったら公式ドキュメントを読もうな。
以上。