Node.jsとSocket.IOでリアルタイムのチャットアプリを作ってみる


前回、Node.jsとSocket.IOでリアルタイムでやりとりができるチャットアプリを作ってみた。

Socket.IOのおかげで少ないコードでチャットアプリを作ることが出来たけれども、

これだと世間で見られるチャットアプリとは程遠い。


というわけで、

前回の簡易版に追加でカスタマイズしていく形で、

Socket.IOにより触れていくことにする。


チャットアプリで欲しい機能といえば、



今接続している方で誰が入力中なのか?は欲しいところ。

というわけで、入力中の表示の追加を試してみる。


ファイルの構成は前回同様

workspace
├── index.html
└── server.js

こんな感じ。


それでは、各ファイルに入力中のイベントを追加してみる。


server.js

/** サーバの構築とプロトコルをWebSocketにUpgradeするところまでは省略

//2.イベントの定義
io.on("connection", function(socket){

	// 接続開始のカスタムイベント(接続元ユーザを保存し、他ユーザへ通知)
	socket.on("connected", function(name){ /** 省略 **/ });

	// メッセージ送信カスタムイベント
	socket.on("publish", function(data){ /** 省略 **/ });

	// タイピング開始
	let nowTyping = 0;
	socket.on("start typing", function(){
		if (nowTyping <= 0) {
			socket.broadcast.emit("start typing", userHash[socket.id]);
		}

		nowTyping++;
		setTimeout(function(){
			nowTyping--;
			if (nowTyping <= 0) {
				socket.broadcast.emit("stop typing");
			}
		}, 3000);
	});

	// タイピング終了
	socket.on("stop typing", function(){
		nowTyping = 0;
		socket.broadcast.emit("stop typing");
	});

	// 接続終了組み込みイベント(接続元ユーザを削除し、他ユーザへ通知)
	socket.on("disconnect", function(){ /** 省略 **/ });
});

server.jsでは、start typingとstop typingいうイベントを追加している。

socket.on("start typing", 処理);の処理内で、socket.broadcast.emit(イベント);というコードがあるが、socketとemitの間にbroadcastというオブジェクトをかますことで、自身以外のすべてのソケット(ブラウザ)に対してイベントを実行するということができる。


続いて、index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>web socket</title>
</head>
<body>
<input type="text" id="msg_input" style="width:200px;">
<button onclick="publishMessage();">語る</button>
<div id="msg"></div>
<div id="system_text"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script>
var systemText = document.querySelector("#system_text");

//イベントとコールバックの定義
var socket = io.connect("http://localhost:8080");

socket.on("connected", function(name){});
socket.on("publish", function(data){ addMessage(data.value);});
socket.on("disconnect", function(){});
socket.on("start typing", function(typinguser){
	systemText.innerHTML += typinguser + 'が入力中';
});
socket.on("stop typing", function(){
	systemText.innerHTML = "";
});

var msgArea = document.querySelector("#msg");
var myName = Math.floor(Math.random()*100) + "さん";
addMessage("貴方は" + myName + "として入室しました");
start(myName);

// 入力開始と同時にタイピンスタートを伝える document.querySelector("#msg_input").addEventListener("keyup", function(){ socket.emit("start typing"); }); function start(name){ /** 省略 **/ } function publishMessage(){ var textInput = document.querySelector("#msg_input"); var msg = "[" + myName + "] " + textInput.value; socket.emit("publish", {value: msg}); textInput.value = ""; // 投稿と同時にタイピング終了を伝える **/ socket.emit("stop typing"); } function addMessage(msg){ /** 省略 **/ } </script> </body> </html>

※buttonタグはonclickでmsg_inputはDOMで指定している雑さは大目に見てください


太字で囲った箇所が追加分で、各所でタイピングの開始と終了のイベントを追加し、

表示中の表記の箇所も追加している。


このコードを実行すると、



このように入力中の表示が追加されるようになった。