WebSocket使ってると、クライアントからサーバーにメッセージ送って、届いたのがはっきりしてから何かしたいことがあったりします。WebSocketの仕様その物にはそういう機能は無いようですが、Socket.IOにはそういう機能があったのでこれが使えました。
(低レベルの話を期待していた方、済みません)
ドキュメントに書いてあることそのままではあるんですが:Sending and getting data (acknowledgements)
Socket.IOのacknowledgements機能
emit
するクライアント側のコード、サーバー側のon
で待ち受けるブロックのコード、のそれぞれでコールバック関数を登録することで、クライアントからのメッセージが届いた時の処理を書けます。処理を書けるということは、届いたことが確認できるということです。
client.js
// クライアント側
var ws = io();
// 色々初期化処理
ws.emit("post", data, function onack(response) {
// データが届いたことを確認できた
doSomethingWith(response);
});
server.js
// サーバー側
// 色々初期化処理
var io = require("socket.io")(server);
io.on("connection", function(user) {
user.on("post", function(data, ack) {
// dataをDBに保存したりする
// ユニークキーが割り振られたりする
data.id = dbRecord.id;
ack(data);// データが届いたことの確認、兼、追加データの通知
});
});
Promiseにしてみる
これだけで終わってもアレなので、Promsieにしてみるとこんな感じでしょうか。
client-with-promise.js
// クライアント側
var ws = io();
// 色々初期化処理
post(data).then(function(response) {
doSomethingWith(response);
});
function post(data) {
return new Promise(function(resolve, reject) {
ws.emit("post", data, resolve);
});
}
ストリームにしてみる
これだけで終わってもアレなので、WAHTWG Streamsのストリームにしてみるとこんな感じでしょうか。
client-with-streams.js
// クライアント側
var ws = io();
// 色々初期設定
userActionStream // 「保存ボタンを押す」とかのアクション
.pipeThrough(actionToData()) // DOMツリーからデータ集めて整形
.pipeThrough(post(ws)) // ここの話なので下に実装置いときます
.pipeTo(soSomethingWithResponse());
function post(ws) {
return new TransformStream({
transform: function(data, enqueue, done) {
ws.emit("post", data, function ack(response) {
enqueue(response);
done();
});
}
});
}
(2015年5月3日版の仕様とリファレンス実装を使っています)