4
6

Socket.ioのemitの動きを理解したい

Posted at

ここでは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についてまだ理解に甘々な部分が多々あると思うので、引き続き勉強していきたいと思います。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6