Help us understand the problem. What is going on with this article?

node.jsを触るために簡単なチャットシステムを作る(メッセージ送信編)

Node.js を触ってみたいと思ったので、備忘録も兼ねて以下に記します。
よりよい方法やバグ等ございましたら、アドバイスいただけると光栄です。

今回は「メッセージ送信編」ということで、クライアントからサーバーへのメッセージの送信の処理を作成します。

※前回 node.jsを触るために簡単なチャットシステムを作る(サーバー接続編) という表題で、サーバー接続の処理を作成していますので、まだな方はこちらを参照ください。

クライアントからサーバーへメッセージを送信する

メッセージ入力フォームを作成

/public/index.html に、以下のメッセージ入力フォームを追加します。

index.html
<form action="">
    <input type="text" id="input_message" autocomplete="off" />
    <button type="submit">Send</button>
</form>

index.html 全体としては、以下のようになります。

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>mychat</title>
</head>
<body>
    <h1>node.js を触ってみた</h1>
    <form action="">
        <input type="text" id="input_message" autocomplete="off" />
        <button type="submit">Send</button>
    </form>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="client.js"></script>
</body>
</html>

クライアント側の処理

/public/client.js の末尾に、下記のようなSendボタンを押したときの処理を追加します。

client.js
// 「Send」ボタンを押したときの処理
$('form').submit(() => {
    const $inp = $('#input_message');
    const text = $inp.val();

    console.log('#input_message :', text);

    if (text) {
        // サーバーに、イベント名 'new message' で入力テキストを送信
        socket.emit('new message', text);
        // テキストボックスを空に
        $inp.val('');
    }
    // フォーム送信はしない
    return false;
});

/public/client.js 全体としては、以下のようになります。

client.js
'use strict';

// クライアントからサーバーへの接続要求
const socket = io.connect();

// 接続時の処理
socket.on('connect', () => {
    console.log('connect');
});

// 「Send」ボタンを押したときの処理
$('form').submit(() => {
    const $inp = $('#input_message');
    const text = $inp.val();

    console.log('#input_message :', text);

    if (text) {
        // サーバーに、イベント名 'new message' で入力テキストを送信
        socket.emit('new message', text);
        // テキストボックスを空に
        $inp.val('');
    }
    // フォーム送信はしない
    return false;
});

サーバー側の処理

server.js の「接続時の処理」の中に、下記処理を追加します。

server.js
// 新しいメッセージ受信時の処理
socket.on('new message', (strMessage) => {
    console.log('new message', strMessage);
});

server.js 全体としては、以下のようになります。

server.js
'use strict';

// モジュール
const http     = require('http');
const express  = require('express');
const socketIO = require('socket.io');
const moment   = require('moment');

// オブジェクト
const app    = express();
const server = http.Server(app);
const io     = socketIO(server);

// 定数
const PORT = process.env.PORT || 3000;

// グローバル変数
let iCountUser = 0; // ユーザー数

// 接続時の処理
io.on('connection', (socket) => {
    console.log('connection');

    // 切断時の処理
    socket.on('disconnect', () => {
        console.log('disconnect');
    });

    // 新しいメッセージ受信時の処理
    socket.on('new message', (strMessage) => {
        console.log('new message', strMessage);
    });
});

// 公開フォルダの指定
app.use(express.static(__dirname + '/public'));

// サーバーの起動
server.listen(PORT, () => {
    console.log('server starts on port: %d', PORT);
});

動作を確認する

サーバーを立ち上げた状態で、
http://localhost:3000 にアクセスします。

「aaa」と「あああ」というメッセージをフォームに入力し、「Send」ボタンを押します。
Google Chrome のデベロッパーツールの Console に、connectに続いて、
#input_message : aaa
#input_message : あああ
と表示されます。

下記のようにサーバー側で connection に続いて、
new message aaa
new message あああ
と表示されれば完了です。

node server.js
server starts on port: 3000
connection
new message aaa
new message あああ

サーバーからクライアントへメッセージを拡散する

サーバー側の処理

server.js の「接続時の処理」の中に、下記処理を追加します。

server.js
// 送信元含む全員に送信
io.emit('spread message', strMessage);

server.js 全体としては、以下のようになります。

server.js
'use strict';

// モジュール
const http     = require('http');
const express  = require('express');
const socketIO = require('socket.io');
const moment   = require('moment');

// オブジェクト
const app    = express();
const server = http.Server(app);
const io     = socketIO(server);

// 定数
const PORT = process.env.PORT || 3000;

// グローバル変数
let iCountUser = 0; // ユーザー数

// 接続時の処理
io.on('connection', (socket) => {
    console.log('connection');

    // 切断時の処理
    socket.on('disconnect', () => {
        console.log('disconnect');
    });

    // 新しいメッセージ受信時の処理
    socket.on('new message', (strMessage) => {
        console.log('new message', strMessage);

        // 送信元含む全員に送信
        io.emit('spread message', strMessage);
    });
});

// 公開フォルダの指定
app.use(express.static(__dirname + '/public'));

// サーバーの起動
server.listen(PORT, () => {
    console.log('server starts on port: %d', PORT);
});

クライアント側の処理

/public/client.js の末尾に、下記のようなSendボタンを押したときの処理を追加します。

client.js
// サーバーからのメッセージ拡散に対する処理
socket.on('spread message', (strMessage) => {
    console.log('spread message :', strMessage);

    // 拡散されたメッセージをメッセージリストに追加
    const li_element = $('<li>').text(strMessage);
    $('#message_list').prepend(li_element);
});

/public/client.js 全体としては、以下のようになります。

client.js
'use strict';

// クライアントからサーバーへの接続要求
const socket = io.connect();

// 接続時の処理
socket.on('connect', () => {
    console.log('connect');
});

// 「Send」ボタンを押したときの処理
$('form').submit(() => {
    const $inp = $('#input_message');
    const text = $inp.val();

    console.log('#input_message :', text);

    if (text) {
        // サーバーに、イベント名 'new message' で入力テキストを送信
        socket.emit('new message', text);
        // テキストボックスを空に
        $inp.val('');
    }
    // フォーム送信はしない
    return false;
});

// サーバーからのメッセージ拡散に対する処理
socket.on('spread message', (strMessage) => {
    console.log('spread message :', strMessage);

    // 拡散されたメッセージをメッセージリストに追加
    $('#message_list').prepend($('<li>').text(strMessage));
});

メッセージをビュー側に表示

/public/index.html のメッセージ入力フォームの下に、以下のメッセージリストを追加します。

index.html
<ul id="message_list"></ul>

index.html 全体としては、以下のようになります。

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>mychat</title>
</head>
<body>
    <h1>node.js を触ってみた</h1>
    <form action="">
        <input type="text" id="input_message" autocomplete="off" />
        <button type="submit">Send</button>
    </form>
    <ul id="message_list"></ul>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="client.js"></script>
</body>
</html>

動作を確認する

メッセージの表示

サーバーを立ち上げた状態で、
http://localhost:3000 にアクセスします。

「aaa」と「あああ」というメッセージをフォームに入力し、「Send」ボタンを押します。

送信したメッセージが、リスト表示されます。

別ブラウザでもメッセージを表示

ブラウザを別に立ち上げ、
http://localhost:3000 にアクセスします。

「bbb」と「いいい」というメッセージをフォームに入力し、「Send」ボタンを押します。

送信したメッセージが、両方のブラウザに、即座に、リスト表示されれば完了です。

最後に

今回作成する機能としては以上となります。

ここで作成した機能をベースに、
以下のような機能や他にも自分で思いついた機能などを追加してみるのも良い学習になると思います。

  • メッセージに時刻を表示
  • メッセージに発信者名を表示
  • ユーザーの入室、退室を表示

ソースコードは以下に載せていますので、よろしければ参照ください。
https://github.com/genki-sano/express-socketio-chat

関連記事

kaonavi
クラウド人材管理ツール「カオナビ」の製造・販売・サポートを行い、企業の人材管理にイノベーションを起こすことを目的としている会社
https://www.kaonavi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away