ここではWebSocketの詳細な話はしません。下記の記事がわかりやすいのでWebSocketについて知りたい方は下の記事から🙇
Socket.ioとは?
WebSocketの実装を容易に行うことができるライブラリです。公式チュートリアルではJavaScriptを用いて説明されていますが、JavaやPythonなど、JavaScript以外にも実装可能みたいです。でも基本的にExpress.jsと一緒に動かすパターンが多いんじゃないかな?と個人的に思ってます。
socket.emit()やsocket.to(room).emit()の動き
WebSocketを実装をしていてよく理解していなかったのが、この emit()
の動きです。
この emit()
というのがイベント発火のためのメソッドで、クライアントからサーバーへの送信は言わずもがな、サーバーからクライアントへの送信もできるというところ がHTTPとの大きな違いでもあると思います。
自分はこの emit()
を以下のように認識していました。
// サーバーと接続しているクライアント全てにsend_messageイベントを発火
socket.emit('send_message', msg)
// JOINしているユーザー全てにイベントを発火
socket.to(roomId).emit('send_message', msg)
どちらも 誤認識 でした。
前提
socket.ioでは、接続した全てのユーザーに対して 一意の socketId
が割り振られます。この socketId を利用してイベントを発火させたりします。
socket.emit('event_name')
socket.emit('event_name')
は、サーバーとWebSocketを通じて接続している全てのユーザーではなく、socket
のオブジェクトに含まれているsocketIdに対してのみ イベントを発火するみたいです。つまりこれは一人のユーザーにしか発火しません。
io.on('connection', (socket) => {
// このsocketは接続した一人のユーザー
socket.on('receive_chat_message', msg => {
// だからemitするのも、リクエストをしてきたユーザーに対してイベントを発火させている
socket.emit('send_messsage', msg);
});
})
なので、ここの socket.emit()
は、リクエストをしてきたユーザーに対してのみイベントを発火させるもの 。
socket.to(room).emit('event_name')
じゃあどうやって他のユーザーに対してイベントを発火させるの?チャットアプリとか開発する時に、送信した内容が自分にしか返ってこないなら意味ないじゃないか!
それがsocket.ioの room
機能になります。
io.on('connection', (socket) => {
socket.on('room_join_request', () => {
const roomId = "hoge";
// "hoge"というroomにjoinする
socket.join(roomId);
// "hoge"というroomにjoinしている'このsocketのユーザー以外の'ユーザーにのみイベントを発火する
socket.to(roomId).emit('send_message', 'User joined "hoge" room!!');
})
})
上記のコードでは、"hoge"というroomIdを用意し、room_join_request
のイベントをemitしてきたユーザーを"hoge"にjoinさせ、最終的に"hoge"に所属しているroomのユーザー全てに対して"新しいユーザーが入室したことを伝える"イベントを発火させています
この時注意することは、socket.to(roomId).emit(...)
はそのroomに所属している全てのユーザーに対してイベントを発火させるのではなく、socket
オブジェクトのユーザー以外のroomに所属しているユーザー に対してのみイベントを発火させるのです。
つまり、上記のコードで言う
socket.to(roomId).emit('send_message', 'User joined "hoge" room!!');
の部分は、socket
以外の"hoge"に所属しているユーザーに送信しているということです。
ここが個人的に引っかかった部分でありました。
socket.to(roomId)
と記述しているくらいだから、そのroomに所属している全てのユーザーに対して行うと思いませんか?でも実際は異なって、正確に説明(合っているか分からないが)すると、
ある room
に対して、socket
オブジェクトにある socketId
以外の、 room
に属している全てのsocketId
に対してイベントを発火させる
ということになるはずです。
最後に
WebSocket然りsocket.ioについてまだ理解に甘々な部分が多々あると思うので、引き続き勉強していきたいと思います。