.net column

.NET開発者のためのブログメディア

JavaScriptでチャットを実現する方法|例を上げて解説

2020年06月08日

SE
JavaScriptでチャットを実現する方法には、どのようなものがあるのでしょうか?

PM
具体的な例をご紹介していきましょう。

チャットの仕組み

いきなりタイトルを裏切るようですが、JavaScriptのみでチャットは実現できません。JavaScriptはWebの技術としては「静的」な技術です。Webサーバーからクライアントに「静的」なコードが渡されて、クライアントからサーバーの内容を変えることはできません。サーバーの内容を変えるのは「動的」な技術です。フロントエンド、バックエンドと言われます。チャットはWebサーバーがテキストなどのやりとりを仲介しなくてはいけないため、バックエンドの構築が不可欠になってきます。とはいえ、JavaScriptもチャットに対応したもので開発しないと、チャットはできません。この記事では、チャットを実現する技術であるWebSocketを例にとり、JavaScript側のコードを解説します。

WebSocketとは

WebSocketとは、バックエンドの言語に備わった仕組みで、サーバーがデータの送受信を行います。

WebSocketの仕組み

Python+Djangoだとredisサーバーというものを立ち上げ、channnelsというライブラリを使って行います。Pythonコードについては割愛します。WebSocketを使うJavaScriptコードは、チャットの画面で動くように書きます。

JavaScriptコード

JavaScriptは例えば以下のようなコードになります。const roomName = JSON.parse(document.getElementById(‘room-name’).textContent);protocol = window.location.protocol;p = “”wss://””;if (protocol == “”http:””) { p = “”ws://””;}const chatSocket = new WebSocket( p + window.location.host + ‘/ws/chat/’ + roomName + ‘/’);chatSocket.onmessage = function(e) { const data = JSON.parse(e.data); const guestIdDom = document.querySelector(‘#guest-id’); guestIdDom.value = data.guest_id; const guestNameDom = document.querySelector(‘#guest-name’); guestNameDom.value = data.guest_name; n = document.createElement(“”div””); date = new Date(); h = date.getHours(); m = date.getMinutes(); n.innerHTML = (チャットのメッセージの中身); $(‘#data’).append(n);};chatSocket.onclose = function(e) { console.error(‘Chat socket closed unexpectedly’);}; document.querySelector(‘#send’).onclick = function(e) { const messageInputDom = document.querySelector(‘#id_talk’); const message = messageInputDom.value; const guestIdDom = document.querySelector(‘#guest-id’); const guest_id = guestIdDom.value; const guestNameDom = document.querySelector(‘#guest-name’); const guest_name = guestNameDom.value; chatSocket.send(JSON.stringify({ ‘message’: message, ‘guest_id’: guest_id, ‘guest_name’: guest_name }));};var elementHtml = document.documentElement;var bottom = elementHtml.scrollHeight – elementHtml.clientHeight;window.scroll(0, bottom);解説します。ws://wss://というのはWebSocketサーバーのプロトコルです。それぞれhttp、httpsに該当します。その中にチャットを交換する「場所」を作ります。chatSocket.onmessageは「チャットが届いたとき」の処理です。JavaScriptのイベント処理です。画面上に描画しています。chatSocket.oncloseは「場所」が閉じたときの処理です。エラーメッセージを出しています。document.querySelector(‘#send’).onclickは「送信ボタンを押したときの処理」で、チャットを発信しています。JavaScriptのイベント処理です。chatSocket.sendが発信処理です。チャットはJSONでやりとりします。JSONの扱いについては割愛します。最後の3行は、JavaScriptで画面の下端までスクロールさせる処理です。

一筋縄ではいかない

JavaScript自体はこの程度なのですが、WebSocketのバックエンド構築に多大な手間がかかります。一筋縄ではいきません。例えば、channnelsのために書くPythonコードは# chat/consumers.pyimport jsonfrom asgiref.sync import async_to_syncfrom channels.generic.websocket import WebsocketConsumerclass ChatConsumer(WebsocketConsumer): def connect(self): self.room_name = self.scope[‘url_route’][‘kwargs’][‘room_name’] self.room_group_name = ‘chat_%s’ % self.room_name # Join room group async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name ) self.accept() def disconnect(self, close_code): # Leave room group async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name ) # Receive message from WebSocket def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json[‘message’] guest_id = text_data_json[‘guest_id’] guest_name = text_data_json[‘guest_name’] # Send message to room group async_to_sync(self.channel_layer.group_send)( self.room_group_name, { ‘type’: ‘chat_message’, ‘message’: message, ‘guest_id’: guest_id, ‘guest_name’: guest_name } ) # Receive message from room group def chat_message(self, event): message = event[‘message’] guest_id = event[‘guest_id’] guest_name = event[‘guest_name’] # Send message to WebSocket self.send(text_data=json.dumps({ ‘message’: message, ‘guest_id’: guest_id, ‘guest_name’: guest_name }))と、なかなかの難物で、他にも仕組みづくりが難しくなっています。興味がある方は以下のリンクをご覧になってください。

https://channels.readthedocs.io/en/latest/tutorial/index.html

SE
WebSocketのバックエンド構築が難しそうですね。

PM
そうですね。参考リンクもあるので、この機会にぜひ挑戦してみましょう!

WebSocketのバックエンド構築にも挑戦してみよう

JavaScriptのコードを書くよりも、バックエンド構築の方が難易度高いように感じる人もいるでしょう。機会を見つけて、難しそうだと思って今まで敬遠していたものに挑戦してみましょう。その結果、新たな知識や経験が得られ、スキルアップにも繋がります。


.NET分野でのキャリアアップをお考えの方は、現在募集中の求人情報をご覧ください。

求人一覧

また、直接のエントリーも受け付けております。

エントリー(応募フォーム)