N予備校「プログラミング入門Webアプリ」を受講しています。
今回は第4章9,10節です。
AJAX
Asynchronous JavaScript + XML
クライアント-サーバー間で、非同期に通信が行える。
複数ページで実装していたサイトを単一のページで複数の機能(AJAXやWebSocket)を表現したアプリケーションを、シングルページアプリケーション(SPA)という。
const serverStatus = require('./routes/server-status');
app.use('/server-status', serverStatus);
const loadavg = $('#loadavg');
setInterval(() => {
$.get('/server-status', {}, (data) => {
loadavg.text(data.loadavg.toString());
});
}, 10);
'use strict';
const express = require('express');
const router = express.Router();
const os = require('os');
router.get('/', (req, res, next) => {
res.json({ loadavg: os.loadavg() });
});
module.exports = router;
ちょっとわかりにくい。
json形式はJavaScriptのオブジェクトの書き方ができるので、{loadavg: os.loadavg()}
となる。
最初にapp.js
が読み込まれ、 /server-status
にアクセスされると、server_status.js
が呼び出される。
なお、server-status.js
のget
は、自分のことを指すので /
になる。
server-status.js
のres.json
の値がentry.js
のdata
に格納される。
ポーリング
クライアントからサーバーに対して一定間隔に情報を取得する実装方法
今回みたいな10ミリ秒はかなり負荷がかかる。
ロードアベレージ
1 CPU における単位時間あたりの実行待ちとディスクI/O待ちのプロセス数
1を超えるとビジー状態。
同一生成元ポリシー(Same-Origin Policy)
ブラウザのセキュリティ上の考え方で、 コンテンツが同一の生成元から提供されているかを確認し、外部からの干渉を防ごうとするポリシー
今回でいうと、
スキーム: http
ホスト: localhost
ポート: 8000
この三つが同じでないとAJAXでは弾かれる
同一生成でない領域へのアクセスのことをクロスオリジンリクエストという。
WebSocket
Webサーバーとブラウザ間で利用できる双方向通信の規格
リアルタイムを優先するなら、AJAXよりもWebSocket。
プル通信: 常にクライアントがサーバーに情報を要求する(AJAX)
プッシュ通信: クライアントだけでなく、サーバーからも任意のタイミングでクライアントに情報を送信できる(WebSocket)
リクエストがあると、接続を維持し続ける。
Socket.IO を利用する
yarn add socket.io@2.1.1 socket.io-client@2.1.1
サーバー側
var server = http.createServer(app);
const io = require('socket.io')(server);
const os = require('os');
function emitServerStatus(socket){
socket.emit('server-status', {loadavg: os.loadavg()});
console.log(`server-status event emitted.`);
}
io.on('connection', function(socket){
setInterval(emitServerStatus, 10, socket);
});
クライアント側
const loadavg = $('#loadavg');
import io from 'socket.io-client';
const socket = io('http://localhost:8000');
socket.on('server-status', (data) => {
loadavg.text(data.loadavg.toString());
});
socket.on('connect', () => {
console.log('接続しました');
});
socket.on('disconnect', () => {
console.log('切断しました')
});
connection
イベントは、クライアントから接続要求があったときに発生する。
socket.emit('server-status', {})
全てのクライアントに向けて、server-status
というイベントを発生させる。
まとめ
AJAXは以前にも何回か使ったことはあるけれど、WebSocketははじめて。サーバーを閉じて接続を切断した時にもクライアントが延々と情報を送り続けようとするのをみても、単純にどっちがいいってこともなさそう。
しかしexpress
にまだ慣れてないのもあって、どこに何を書けばいいのかというのがぱっと判断できないのが悩み。