インターラプト開発者ブログ

インターラプトのプロダクト・サービスに関する開発ブログ

擬似リアルタイムとリアルタイムの両立

最近開発で少し悩んだことがありまして、 JavaScriptで例えばですがチャット機能のようなものを作っていました。

チャットなのでリアルタイムに流れていきますよね。 投稿時はAjaxで、画面を更新せずにサーバーへPOSTし、チャットメッセージが送られるような仕組みです。

普通に実装すると、チャットメッセージを投稿しても、すぐには画面には表示されません。送信リクエストのレスポンスを受け取り、エラーがなければ画面表示します。

数秒遅れて画面に出る

するとどうでしょう、画面には数秒遅れて表示されます。あんまりリアルタイムに感じません。なので、投稿したらすぐに画面に表示したくなります。

それが、サーバーに送信したと同時にその内容をそのままクライアントにサーバーから受け取ったと見なして表示させてしまう方法です。

これを疑似リアルタイムと呼ぶことにしました。レスポンスを受け取ったときは、前者にはidが無いので、idを差し替えます。

これでリアルタイムにチャットが出来るような見え方になりました。

そこに本当のリアルタイム処理を入れると...

疑似リアルタイムだと、投稿時は本当にすぐに送られているようにみえるのですが、受信はリアルタイムではありません。受信もリアルタイムにするには、「WebSocket」を使用します。他にもWebRTCなどでも可能です。

FirebaseやAppSyncでも手軽に実装可能で、専用サービスを利用するとリアルタイムの実装の敷居は低いです。

このリアルタイム処理を入れると、挙動が怪しくなります。

一瞬二つにみえる

疑似リアルタイムでは、まだidのない疑似投稿を即座に表示させる方法です。リアルタイム投稿にはidがあるものの、疑似投稿のidが分からないために、消して差し替えることが出来ません。

リアルタイム投稿は、投稿時のレスポンスが返ってくる速さよりも早い場合があるため、その間、投稿が二つに見えてしまうのです。

困った。

対策

対策は、今のところ思いついてるものになりますが 「フロントエンドから一意性のあるIDを付与する」となります。このIDはフロントエンドから生成しているので、IDが特別な意味を持たずフロントエンドから改変可能な(改変してもセキュリティに影響のない)IDである必要があります。

なので、本来のIDとはわけた方が良いです。

これにより、投稿時レスポンスまたはリアルタイムによって受け取った投稿に同じIDが合った場合は、差し替えることにより、一瞬二つ表示ことを回避できます。

最後に

もっといい方法あると思うのですが、(メッセージ内容と日付で比較するなど) なかなかこれだという方法はないですね。