はじめに
『存在しないクイズ』
というアプリを作りました。
▼URL
https://sonzaisinai.herokuapp.com
この世界に存在しないものを四択の中から選ぶクイズアプリです。
同じルームにいる人と対戦ができます。
▼ソースコード
GitHub
現在できるのはルーム対戦と問題の投稿です。
今後はランキングやランダム対戦などを追加していきます。
この記事ではSocket.ioのRoomsとHeroku Postgresに関して備忘録を残しておこうと思います。
Node.jsについて
公式曰く「非同期のイベント駆動のJavaScript環境」
ざっくりと説明すると、サーバサイドをJavaScriptで記述できます。
今回はクライアント-サーバー間の通信のためにSocket.ioと呼ばれるライブラリを使用しました。
Herokuについて
いわゆる「PaaS(Platform as a Service)」
200種類を超えるAdd-on(拡張機能)があり、GitHubと連携してアプリをデプロイすることもできます。
基本的には無料ですが
- 無料で使用できるリソースに制限がある
- 無料の場合30分アクセスがないとスリープする
- Gitがインストールされている必要がある
- add-onを使用するためには、クレジットカードを登録しなければならない
今回はインフラとデータベース(Heroku Postgres)を使用しました。
備忘録
Socket.ioの双方向通信
Socket.ioはクライアント-サーバ間の双方向の通信を実現するためのNode.jsライブラリです。
ざっくりとよく使うものをまとめました。
// モジュールを読み込む
const express = require('express');
const http = require('http');
const socketIO = require('socket.io');
// サーバを構築する
const app = express();
const server = http.Server(app);
const io = socketIO(server);
イベントハンドラを設定します。
端的に言うと、"event"を受信したときに内側の処理が実行されます。
// イベント("event")とデータ(param)を受信する
socket.on("event", (param) => {
conosle.log("Hello World");
});
サーバ側
サーバはsocket.idという一意のIDでクライアントを識別します。
io.on('connection', (socket) =>
{
// 全クライアントにイベントとデータを送信する
io.emit("event", param);
// 特定のクライアントにイベントとデータを送信する
io.to(socket.id).emit("event", param);
}
サーバ側(Rooms)
Socket.ioのRoomsを使うことで、ルーム機能を簡単に作ることができます。
io.on('connection', (socket) =>
{
// クライアントをルーム(strRoomName)に参加させる
socket.join(strRoomName);
// ルーム内の全クライアントにイベントとデータを送信する
io.to(strRoomName).emit("event", param);
// クライアントをルームから退出させる
// 参加者がいなくなればルームは削除される
socket.leave(strRoomName);
}
クライアント側
// サーバと接続する
const socket = io.connect();
// サーバにイベントとデータを送信する
socket.emit("event", param);
// サーバから切断する
socket.disconnect();
Heroku Postgres
Heroku Postgresとは
- Herokuのデータベース
- Add-onsとして簡単に導入できる
- 無料では10,000行・1GBまでリソースを使用できる
データベースにアクセスする
Node.jsは基本的に非同期処理です。
例えば、サーバがデータベースにアクセスして、取得したデータをクライアントに送信する場合には
- サーバがデータベースにアクセスする
- データをクライアントに送信する
- データベースがデータをサーバに渡す
というようなことになり、結果として空のオブジェクトがクライアントに渡ることも起こり得ます。
そのため、データベースからデータを取得する場合には同期処理を使います。
const { Client } = require('pg');
// table内の全データを取得する
const selectAll = async () =>
{
const client = new Client(
{
connectionString: process.env.DATABASE_URL,
ssl:
{
rejectUnauthorized: false
}
}
);
try
{
// client.connect()の結果が返されるまで待機する
await client.connect();
// client.query()の結果が返されるまで待機する
const result = await client.query(
"SELECT * FROM table");
return result.rows;
}
catch(err)
{
console.log(err.stack);
}
finally
{
// client.end()の結果が返されるまで待機する。
await client.end();
}
}
おわりに
▼お世話になりました