July 2, 2017

Ember + SocketIO with Express

目的 & 目標

クライアントサイドはEmberを使い、リアルタイムにブラウザ間のやり取りをさせる。
ボタンを押したら相手に通知されるチャットのようなものを作る。
通信はWebsocketで行い、Socket.IOを使う。
Socket.IOはExpressで起動させる。

前提

  • Express
    • socket.io を npm でインストールしておくこと
    • express の環境を作っておくこと
  • Ember
    • bower install socket.io-client --savesocket.io-clientを入れておくこと
    • ember-cli-build.jsapp.import('bower_components/socket.io-client/socket.io.js');と記載しておくこと

サーバ側(Express)

① socket.js

module.exports = Socket;
function Socket(server, options) {
  var io = require("socket.io")(server);

  io.on("connection", function (socket) {
    console.log("connection");
    io.emit("connect");

    /**
     * Deliver message
     */
    socket.on("deliverMessage", function(data) {
      console.log("Received: %s", data.body);
      io.emit("receiveMessage", {
        "success": true,
        "message": data
      });
    });

    /**
     * Disconnect
     */
    socket.on("disconnect", function(){
      console.log("disconnected");
    });
  });
}

② bin/www (express起動ファイル)

/**
 * Create HTTP server.
 */

var server = http.createServer(app);
// ↓ 追記
/**
 * Create Socket.io
 */
var socket = require('../socket')(server);
// ↑ 追記

Ember側

③ services/websocket.js

import Ember from "ember";

export default Ember.Service.extend({
  init() {
    let socket = this.socket = io();
    socket.on("receiveMessage", function (data) {
      console.log("received", data);
    }.bind(this));
  },

  /**
   * sendMessage
   */
  sendMessage: function (data) {
    this.socket.emit("deliverMessage", data);
  }
});

④ controllers/chat.js

import Ember from 'ember';

export default Ember.Controller.extend({

  websocket: Ember.inject.service('websocket'),

  actions: {
    sendMessage() {
      var data = {'message': this.get('message')};
      this.get("websocket").sendMessage(data);
    }
  }
});

⑤ templates/chat.hbs

{{textarea value=message id="message" row="2"}}
<button {{action "sendMessage"}} id="submit" class="ui right primary button">
  Submit
</button>

処理の流れ

  1. ⑤のテンプレートのボタンをおした時、sendMessageが実行される。このsendMessageは④のcontrollers/chat.jsに宣言されているsendMessage
  2. ④のsendMessageが実行されるとthis.get("websocket").sendMessage(data);で、③のsendMessageを実行する。
  3. ③のsendMessageでは、this.socket.emit("deliverMessage", data);で①のdeliverMessageを呼び出す(ここでようやくサーバサイドへ)
  4. deliverMessageでは、io.emit("receiveMessage", ...で、③のsocket.on("receiveMessage"...を呼び出す(クライアントサイドへ戻る、接続している全員にメッセージが送信される)
  5. ③のreceiveMessageでデータを加工したりして、画面に表示したりする(サンプルではconsole.logを出しているだけ)

ファイル構成

Express自体に必要なファイルや、Ember自体に必要なファイルは記載していないので注意。
①〜⑤は上記の①〜⑤と対応。

SocketIO側(Express)

  • ./
  • bin/www(②)
  • socket.js(①)

Ember側

  • ./
    • services/websocket.js(③)
    • controllers/chat.js(④)
    • templates/chat.hbs(⑤)