初心者向け学習方法一覧はこちら
はじめに
今回はチャットサポートアプリのサーバーサイドの処理を実装します。
サーバーはクライアントからメッセージを受け取って応答メッセージを返却します。
クライアントサイドが完成していることが前提となりますので、まだ作成していない方は前回の記事
チャットサポートアプリのサンプルコードはGitHubにて公開しています。
クライアント・サーバーシステムとは?
クライアント・サーバーシステムとは、データや処理結果をリクエストするクライアントとリクエストを受けて結果を返すサーバーという2つの役割に分けてシステムを構築する仕組みのことです。
今回作成するチャットサポートアプリではクライアントをHTMLとjQueryで、サーバー側の処理をNode.jsで記述します。 アプリの完成イメージを示します。
アプリの動作の流れは下記のとおりです。
- アプリへのアクセス時
- メッセージ送信時
1.クライアントは、サーバーにURLでアクセスする。
2.サーバーは、クライアントにWebアプリのページを返却する。
3.クライアントは、サーバーにメッセージを送信する。
4.サーバーは、クライアントの送信メッセージに対応した返却メッセージを生成し、クライアントに返却する。
開発の準備をしよう
前回作成した「chat-support」フォルダ直下に「server.js」と「response.txt」の2つのファイルを作成します。
「chat-support」フォルダを開いた状態で右クリックのメニューから「統合ターミナルで開く」を選択してターミナルを開きます。 以下のコマンドを実行して、nmp管理の初期化とexpressとmulterというモジュールをインストールします。
npm init -y
npm i express multer
インストールする2つのモジュールは一括で指定しています。 文字間の半角スペースを忘れないようにしてください。
コマンドを実行するとフォルダ内にnode_modulesフォルダ、package-lock.json、package.jsonが生成されます。 作成したフォルダとファイルの内容はこのようになります。
静的コンテンツファイル(HTML、CSS)配信サーバーの準備
server.jsの内容を記述していきます。
全体像はこのようになります。 「// TODO」とコメントを記載している箇所は、後ほど内容を作成します。
// モジュール準備
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const app = express();
app.use(multer().none());
// 静的コンテンツ(HTMLファイル)の返却準備
app.use(express.static('public'));
// チャット用エンドポイント
app.post('/chat', function (req, res) {
// TODO
});
// サーバーを起動する
const port = 3000;
app.listen(port, function () {
console.log('Node.js Server Started: http://localhost:' + port);
});
まずは使用するモジュール(express、multer)の準備をします。
// モジュール準備
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const app = express();
app.use(multer().none());
次にexpressで静的コンテンツを返却する先として「public」フォルダを設定します。
// 静的コンテンツ(HTMLファイル)の返却準備
app.use(express.static('public'));
次にサーバーを起動するポート番号を3000番に設定します。 これで『http://<サーバーのURL>:<ポート番号>/』のURLで自分の作成したWebサーバーにアクセスが可能になります。
サーバー起動時にターミナルにログを出力します。
// サーバーを起動する
const port = 3000;
app.listen(port, function () {
console.log('Node.js Server Started: http://localhost:' + port);
});
ここまでできたらサーバーを起動してみましょう。 ターミナルで以下のコマンドを実行してください。
node server.js
コマンドを実行したら、Webブラウザで「http://localhost:3000/」にアクセスしてみましょう。 Webアプリが開いて前回作成したinex.htmlの内容が表示されます。
チャット用エンドポイントの準備
まずはresponse.txtの内容を記述します。 CSV形式(カンマ区切り)で受信メッセージとそれに対応する返却メッセージを記述します。 「受信メッセージ,返却メッセージ」の形式です。 区切りは必ず半角カンマにしてください。全角にすると区切りがない文字列として扱われます。
response.txtの例はこのようになります。
おはよう,おはようございます
こんにちは,こんにちは!
おやすみ,おやすみなさい
ユーザーから「おはよう」というメッセージを受信したら「おはようございます」を返却メッセージに設定します。 受信メッセージに「おはよう」という単語が含まれているものであれば「おはようございます」「おはようです」などにも「おはようございます」を返却します。
server.jsのチャット用エンドポイントの処理を記述します。
// チャット用エンドポイント
app.post('/chat', function (req, res) {
const message = req.body.message;
console.log('受信メッセージ:' + message);
let answer = '(回答できずに困っている)';
// 回答をテキストファイルから読み込み
const text = fs.readFileSync('response.txt', 'utf8');
const lines = text.toString().split('\n');
for (let idx in lines) {
const value = lines[idx].split(',');
// あいまい検索(文字列中に送信されてきたメッセージが含まれているか)
if (value[1] !== undefined && message.indexOf(value[0]) != -1) {
answer = value[1];
break;
}
}
console.log('返却メッセージ:' + answer);
res.send({
answer: answer
});
});
エンドポイント(アクセス先)に設定した/chatにアクセスがあった際の処理を記述します。 まずはmessageにリクエストパラメーターの受信したメッセージを格納します。
返却メッセージのanswerにはresponse.txtに該当する内容がなかった場合のデフォルトの値として「回答できずに困っている」を設定します。 その後、response.txtの内容を読み込んで配列に格納します。 まずはlinesという名前の配列に改行コードを区切り文字として格納していきます。 つまり1行ずつ読み込むということです。 そして繰り返し処理の中でvalue配列にlinesの値を半角カンマ区切りで配列に格納します。 図で解説するとこのようになります。
if文の中ではvalue[1]、つまり返却メッセージが存在する、かつ受信メッセージの内容にvalue[0]の文字列が含まれている場合に、返却メッセージにvalue[1]の値を設定します。
条件を満たさなかった場合は次のlinesの値をvalue配列に格納して条件を満たしているかチェックするという処理を繰り返します。 条件を満たした場合か、linesの最後までチェックし終わったら終了です。 最後までチェックして該当するものがなければデフォルト値がそのまま返却メッセージとなります。
返却メッセージのanswerはJSON形式でクライアントに返却します。
クライアント側のメッセージ送信処理の作成
前回はクライアント側で「送信」ボタンをクリックした際に呼び出すsendMessage関数の処理をアラートメッセージの表示で仮置きしていました。 この関数の内容を実際にメッセージを送信する処理に修正します。 sendMessageは5つの処理を行います。
- 入力されたメッセージを取得
- 取得したメッセージをユーザー側のチャットボックスに表示する(sayUser関数を呼び出す)
- 返答メッセージを返すAPIにアクセスする
- 返答メッセージをオペレーター側のチャットボックスに表示する(sayOperator関数を呼び出す)
- 入力されたメッセージをクリアする
先にsendMessage関数から呼び出されるsayUser関数とsayOperator関数を作成します。 どちらも引数に与えられたメッセージをチャット表示部に表示する関数です。
function sayUser(message) {
// 右側にチャットボックスを作成
const chatbox =
'<li><div class="balloon balloon-r">' +
'<p class="say say-r">' +
message +
'</p>' +
'</div></li>';
$('#chat-area').append(chatbox);
// メッセージ最下部までスクロール
$(window).scrollTop($('#chat-area')[0].scrollHeight);
}
function sayOperator(message) {
// 左側にチャットボックスを作成
const chatbox =
'<li><div class="balloon">' +
'<img class="img-circle" src="operator.png" alt="image" />' +
'<p class="say">' +
message +
'</p>' +
'</div></li>';
$('#chat-area').append(chatbox);
// メッセージ最下部までスクロール
$(window).scrollTop($('#chat-area')[0].scrollHeight);
}
sayUserは右側にチャットボックスを作成してメッセージを表示し、sayOperatorは左側にアイコン画像とチャットボックスを表示します。 表示後は、表示済みメッセージの最下部まで自動でスクロールします。
次にsendMessage関数の内容を置き換えます。 前回作成したalertでメッセージを表示するコードは削除してください。
function sendMessage() {
// メッセージを取得
req_message = $('#msg-send').val();
// ユーザが話す
sayUser(req_message);
// APIにアクセスする
const body = new FormData();
body.append('message', req_message);
fetch('./chat', {
method: 'POST',
body,
})
.then((res) => res.json())
.then((v) => {
// オペレーターが話す
sayOperator(v.answer);
});
// メッセージをクリア
$('#msg-send').val('');
}
APIにアクセスする処理はthenでAPIからの返答があるまで待機して、受け取ってから次の処理をするというふうに処理順番を制御します。 これによって返却メッセージを受け取る前にオペレーターのチャットボックスが表示されてしまうことを防いでいます。
最後にShiftキーとEnterキーで「送信」ボタンクリック時と同じようにメッセージを送信できるようにしましょう。 server.jsに下記のコードを追記します。
$(function () {
$(window).keydown(function (e) {
// 「Shift」+「Enter」を押したか
if (e.keyCode === 13 && e.shiftKey) {
sendMessage();
}
});
});
$(function(){〜})というのは特別な記法です。 ページにアクセスされたときに自動的に実行される処理を記述することができます。 ここではウィンドウが活性状態の時は常にキーボードからの入力を監視しています。 そしてキーボードから取得したキーコードが13(Enterキー)かつShiftキー、つまり同時にキーが押されたらsendMessage関数を呼び出します。 Shiftキーは特殊なキーのためこのような記述となります。
動作確認
ここまで作成が完了したらサーバーを起動して動作確認をしてみましょう。 ターミナルで以下のコマンドを実行してください。
node server.js
コマンドを実行したら、Webブラウザで「http://localhost:3000/」にアクセスしましょう。 チャットサポートアプリを開いたらメッセージを送信して返答を確認してみましょう。
response.txtに質問と回答を追記すれば応答を増やすことができます。 色々と追加してチャットサポートの対応範囲を拡げていってください。
まとめ
今回はチャットサポートアプリのサーバーサイドの処理を作成して、実際にメッセージのやり取りができるところまで完成させました。 これまでにJavaScriptの技術として解説してきたものを合わせて1つのアプリが出来上がっています。 不明な点はサンプルコードや他のJavaScriptの記事を参考にしてください。 これまでの解説も実際のコードと照らし合わせることで更に理解が深まると思います。
プログラミングスクールの選び方
転職を検討中の方向け
フリーランス・副業で活躍したい方向け
教養・キャリアアップしたい方向け
給付金について詳しく知りたい方向け
学習方法一覧
- はじめに
- クライアント・サーバーシステムとは?
- 静的コンテンツファイル(HTML、CSS)配信サーバーの準備
- チャット用エンドポイントの準備
- クライアント側のメッセージ送信処理の作成
- 動作確認
- まとめ
- プログラミングスクールの選び方
- 学習方法一覧