メモ: Socket.IO の set と get メソッドは廃止されている

## 前置き
[Illustrator](https://www.adobe.com/jp/products/illustrator.html)で[絵を描いた](https://github.com/toshikisugiyama/illustrator-works)ので、それらを使って[ゲーム](https://toshikisugiyama-images.netlify.app/)を作ってみました。
以前はJavaScriptで絵をただランダムに表示させるだけだったのですが、[Nuxt.js](https://github.com/nuxt/nuxt.js)を使ってゲームに作り変え、遊び方説明ページを加えたり結果を表示させるようにしたり、英語対応やダークモードも実装したりしました。  

&nbsp;
&nbsp;
&nbsp;

しかし、

何かモヤモヤとしたものが残っています。

そして、  

そのモヤモヤは日々募るばかりです。

なぜか?

&nbsp; 
&nbsp;
&nbsp;
&nbsp; 
&nbsp;
&nbsp;


そうです。

**一人でしか遊べないからです。**
**誰かと対戦できるようにしたいのです。**

調べると、

> Socket.IO enables real-time, bidirectional and event-based communication.
It works on every platform, browser or device, focusing equally on reliability and speed.

Node.js用の双方向通信サポートライブラリである[Socket.IO](https://socket.io/)を使うと対戦ゲームに作り変えられるような予感がします。

そこで、Socket.IOを試しに一度使ってみようと思い、『[はじめてのNode.jsプログラミング Kindle版](https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AENode-js%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E6%9D%BE%E5%B0%BE-%E5%8B%87%E4%B9%9F-ebook/dp/B00B2SKE8M/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=socket.io&qid=1589086272&s=digital-text&sr=1-1)』(松尾 勇也 著) の通りにチャットを作ってみました。

## 本題

前置きが長くなりましたが、ここからが本題のメモ書きです。   

以下は[server.jsのこの部分](https://github.com/niusounds/easy-chat/blob/963446a85ff702984c8e706ef5ab58a1aa9ed948/server.js#L13-L35)の抜粋です。

```js:server.js
// socket.ioの設定
io.sockets.on('connection', function(socket) {
	socket.on('login', function(name) {
		// 接続しているユーザー全員にloginを送信
		var time = new Date().toJSON();
		io.sockets.emit('login', time, name);
		// name を記憶
		socket.set('name', name);
	});
	socket.on('post', function(name, text) {
		// 接続しているユーザー全員にpostを送信
		var time = new Date().toJSON();
		io.sockets.emit('post', time, name, text);
	});
	socket.on('disconnect', function() {
		// 接続しているユーザー全員にlogoutを送信
		socket.get('name', function(err, name) {
			var time = new Date().toJSON();
			io.sockets.emit('logout', time, name);
		});
	});
});
```
*（[Matsuo Yuya. Hajimete no Nodejs Programming (Japanese Edition)](https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AENode-js%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E6%9D%BE%E5%B0%BE-%E5%8B%87%E4%B9%9F-ebook/dp/B00B2SKE8M/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=socket.io&qid=1589086272&s=digital-text&sr=1-1) (Kindle の位置No.741-750). Kindle 版. より抜粋）*


`node server.js`としたところ、以下のエラーが発生しました。

```
root@7f37fa299545:/app# node server.js 
/app/server.js:18
        socket.set('name', name);
               ^

TypeError: socket.set is not a function
    at Socket.<anonymous> (/app/server.js:18:16)
    at Socket.emit (events.js:310:20)
    at /app/node_modules/socket.io/lib/socket.js:528:12
    at processTicksAndRejections (internal/process/task_queues.js:79:11)
```

サーバーに接続すると `login` イベントがクライアントに向けて発信されます。その中で[ユーザーの入力した名前を記憶させるための記述の中で `set` を用いています](https://github.com/niusounds/easy-chat/blob/963446a85ff702984c8e706ef5ab58a1aa9ed948/server.js#L21)。

調べてみたところ、

『[node.js - socket.io socket.set and socket.get - what is the callback argument for? - Stack Overflow](https://stackoverflow.com/questions/10360110/socket-io-socket-set-and-socket-get-what-is-the-callback-argument-for#answer-24393900)』の回答によると
> The `get` and `set` functions on the socket object were [removed in version 1.x](https://github.com/Automattic/socket.io/commit/b6a48996898a5cc4112373e91e56d4d1afc46cdf).

`get` と `set` は廃止になっているようです。

[ドットインストール](https://dotinstall.com/lessons/basic_socketio/26408#supplement_832)にも載ってました。
> Socket.IO の 1.0 から socket.set と socket.get メソッドが廃止されたため、そのまま動作させるとエラーが発生してしまいます。

そこで、以下のように修正したところうまくいきました。
（いくつか修正していますが、「**修正**」と書いたところの修正のみがエラーに関連している部分です。）

```js:server.js
//socket.ioの設定
io.sockets.on('connection', socket => {
    socket.on('login', name => {
        //接続しているユーザー全員にloginを送信
        const time = new Date().toJSON()
        io.sockets.emit('login', time, name)
        //nameを記憶
        socket.client_name = name
    })
    socket.on('post', (name, text) => {
        // 接続しているユーザー全員にpostを送信
        const time = new Date().toJSON()
        io.sockets.emit('post', time, name, text) // 修正
    })
    socket.on('disconnect', () => {
        // 接続しているユーザー全員にlogoutを送信
        const time = new Date().toJSON() // 修正
        io.sockets.emit('logout', time, socket.client_name) // 修正
    })
})
```
[GitHub](https://github.com/toshikisugiyama/chat_app_with_nodejs_express_socketio/blob/b4bab8da68ae21b407b05be80e89104239ecff7d/server.js#L11-L30)

## 脇道 

スタイルも修正してみました。
自分が送信したメッセージは画面の右に表示されて、他の人のメッセージは画面の左に投稿されるような見た目にしようと思ったので、以下のことを試しました。

```js:server.js
    socket.on('post', (name, text) => {
        // 接続しているユーザー全員にpostを送信
        const time = new Date().toJSON()
        socket.emit('self-post', time, name, text)
        socket.broadcast.emit('others-post', time, name, text)
    })
```
[GitHub]
(https://github.com/toshikisugiyama/chat_app_with_nodejs_express_socketio/blob/ca1b09e601725a33a1fed6a2d6dd31fc5a27f329/server.js#L20-L25)  

上記のように自分の投稿と他人の投稿をそれぞれ `socket.emit` と `socket.broadcast.emit` を使い分けて別のイベントとして発信することで、

```js:index.html
        socket.on('self-post', (time, name, text) => {
            const content = document.createElement('div')
            content.className = 'self'
            createMessageNode(content, text, time, name)
        })
        socket.on('others-post', (time, name, text) => {
            const content = document.createElement('div')
            content.className = 'others'
            createMessageNode(content, text, time, name)
        })
```
[GitHub](https://github.com/toshikisugiyama/chat_app_with_nodejs_express_socketio/blob/ca1b09e601725a33a1fed6a2d6dd31fc5a27f329/public/index.html#L28-L37)  

自分の投稿には`self`、他人の投稿には`others`のようにそれぞれ別のクラスを設定でき、別のスタイルを割り当てることができました。

![file.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230954/cc661f3c-9ff1-144f-5d38-2bdfa602469f.gif)


## おわりに
次はNuxt.jsで作っている[ゲーム](https://github.com/toshikisugiyama/random_image_game)にSocket.IOを組み合わせて対戦できるようにしたいです。

Nuxt.jsでSocket.IOを使うには『[Nuxt.js (Vue.js) + Express + Socket.IO でリアルタイムWeb (チャット) を体験する](https://qiita.com/rema424/items/c1ef92625ecaf4421e6f)』が参考になるのかなと思っているのですが、やってみないとまだわかりません。

## 参考

- 『[はじめてのNode.jsプログラミング Kindle版](https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AENode-js%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E6%9D%BE%E5%B0%BE-%E5%8B%87%E4%B9%9F-ebook/dp/B00B2SKE8M/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=socket.io&qid=1589086272&s=digital-text&sr=1-1)』(松尾 勇也 著)【[GitHub](https://github.com/niusounds/easy-chat)】
- 『[node.js - socket.io socket.set and socket.get - what is the callback argument for? - Stack Overflow](https://stackoverflow.com/questions/10360110/socket-io-socket-set-and-socket-get-what-is-the-callback-argument-for#answer-24393900)』
- [ドットインストール](https://dotinstall.com/lessons/basic_socketio/26408#supplement_832)