LoginSignup
2
2

More than 5 years have passed since last update.

ActionCableを使うときはEventEmitterと組み合わせてSingletonで使うと捗るかもしれないという話

Last updated at Posted at 2018-04-11

まえがき

最近、Rails5でActionCable + Vue1を使ってSlackっぽい感じのチャット画面を作っているのですが…

  • 「所属ルーム(Slackのチャンネルに相当)」と「ルーム内のメッセージ」を2ペインで表示する
  • 「所属ルーム」と「メッセージ」のコンポーネントはそれぞれ独立したVueファイルに記述されている

という状況で

  • 新規チャットメッセージが配信されたときに各コンポーネントでそれぞれ独立した処理を行いたい
    • 例えば…
      • 「メッセージ」ペインでは配信されたメッセージを末尾に追加する
      • 「所属ルーム」ペインではLINEみたいに新規メッセージが来たルームを一番上に持っていく
      • etc...

上記を実現する必要がありました。2
そんな時にタイトルの件を行ったら良い感じに出来たと思いましたので共有します。

おことわり

  • 各コンポーネント間のイベントの動作順序は問わない前提です
    • 例えば「メッセージペインで行う処理が所属ルームペインで行う処理より後でなければいけない」場合は想定していません
  • 他にも意外なところでマズいかもしれないのでご利用は自己責任でお願いします
  • 筆者はActionCable,Vue共々始めて日が浅い1ので他に良い手法をご存知の方はコメントいただけると幸いです

書いたもの

まず、この様なJSファイルを用意しました。

chat-event.js
import ActionCable from 'actioncable'

const EventEmitter = require('events').EventEmitter

class ChatEventEmitter extends EventEmitter {
  constructor() {
    super()
    const _this = this
    this.cable = ActionCable.createConsumer('/cable')
    this.channel = this.cable.subscriptions.create({channel: "ChatChannel"}, {
      connected: function(){
        _this.emit('connected')
      },
      disconnected: function(){
        _this.emit('disconnected')
      },
      received: function(data){
        _this.emit('received', data)
      }
    })
  }
}

const instance = new ChatEventEmitter()
Object.freeze(instance)

export default instance

そして、各Vueファイルで使うときはこの様になります。

example.vue
<template>
  <!-- 略 -->
</template>

<script>
import ChatEvent from 'chat-event.js'

// 略

export default {
  // 略
}

ChatEvent.on('received', (data) => {  // 配信されたときに呼び出される
  console.log(data) // => コンソールに配信された内容が表示される
  // 以下、行いたい処理
})
// ちなみにChatChannelのアクションを呼び出したいときは以下の様になる
// ChatEvent.channel.perform(...)
</script>

これで期待した動作が実現できました。
コンポーネントの分離性を損なわず、ActionCableのコールバックを利用したい際に使えるので今のところ気に入っています。

あとがき

数種類のチャンネルを貼りたいときは各チャンネルで同様のクラスを作ると良いと思います。
誰かが既にやっててもおかしくないのに誰もやってなさそうなあたりベストプラクティスではない気もする。

参考にしたページ

[Javascript] イベント駆動型の設計ができるEventEmitterに入門
JavaScript/ES6の基本文法とSingletonパターン | 酒と涙とRubyとRailsと


  1. 執筆時点での使用歴はActionCable,Vue共に1ヶ月程度です。 

  2. 通常であればこういう時にVuexが役に立つのだと思います。しかし、ここで作成しているプロダクトは機能が限られており、要求に対してオーバーだと感じたためVuexの導入はしていません。 

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2