【问题标题】:javascript listening multiple socket channels with echojavascript 使用 echo 监听多个套接字通道
【发布时间】:2017-10-17 02:43:38
【问题描述】:

我尝试编写一个聊天应用程序。我使用(在服务器端):php laravel 5.4pusher 和(在客户端)vue.jslaravel-echo

我已经做了一个聊天群,什么是“公共聊天室”。现在我正在开发私人聊天室。

我的问题:什么是最佳做法(在客户端)来监听用户所属房间的所有频道。

我的目标:检查(例如在 facebook messenger 网页上)私人和公共房间的每个频道。

现在我在chat-window 组件中有这个:

created() {
  axios.get('/chatroom').then(response => {
      this.chatRooms = response.data;
      console.log('get /chatroom response: ' + response.data);
  });

  axios.get('/messages').then(response => {
      this.messages = response.data;
      console.log('get /messages response: ' + response.data);
  });

  Echo.join('chatroom')
      .here((users) => {
          this.usersInRoom = users;
      })
      .joining((user) => {
          this.usersInRoom.push(user);
      })
      .leaving((user) => {
          this.usersInRoom = this.usersInRoom.filter(u => u != user)
      })
      .listen('MessagePosted', (e) => {
          this.messages.push({
              message: e.message.message,
              user: e.user
          });
      });
  }
});

但这只会监听chatroom 频道。客户端如何监听所有聊天室(this.chatRooms)?

提前感谢您的回答!

【问题讨论】:

  • 你解决了吗?
  • 谢谢这个问题,是的,我会写解决方案

标签: javascript laravel npm vue.js laravel-echo


【解决方案1】:

所以我发现每个用户都必须是自己的频道。

然后我修改了我的chat-window 组件:

<template lang="html">
  <div class="panel panel-default">
      <div class="panel-heading" style="height: 60px">
        <chat-room-picker :chatrooms="chatRooms" :newmessage="newmessage" :defaultchatroomid="pickedchatroomid" class="pull-left" v-on:chatroompicked="chatroompick"></chat-room-picker>
        <chat-room-creator class="pull-right"></chat-room-creator>
      </div>
        <chat-room :chatroomid="pickedchatroomid" :newmessage="newmessage"></chat-room>
  </div>
</template>

<script>
export default {
  data() {
    return {
     userId: loggedUserFS.id,
     userName: loggedUserFS.name,
     chatRooms: chatRoomsFS,
     pickedchatroomid: defaultChatRoomIdFS,
     newmessage: {},
    }
 },
 methods: {
   chatroompick(id) {
     this.pickedchatroomid = id;
   },
 },
 created() {
  // this.getCookiesParams();
  var tmp = this.chatRooms[0];
  this.pickedchatroomid = tmp.id;
   var channelName = 'chat-' + this.userId;
   console.debug(channelName + ", channel init.");
   window.Echo.join(channelName)
       .listen('NewMessageEvent', (e) => {
           console.debug("incoming message on " + channelName + ": " + JSON.stringify(e));
           console.debug(e.message.chatRoom_id + "==" + this.pickedchatroomid);
           console.debug(channelName +" : "+ e.message.chatRoom_id + "==" + this.pickedchatroomid);
           // TODO: finish it
           if(e.message.chatRoom_id == this.pickedchatroomid) { // if the reciced message comes from the pickedchatroom
             console.debug("reciced message comes from the pickedchatroom!");
             this.newmessage = e;
           } else { // if the reciced message does not come from the pickedchatroom
             this.newmessage = e;
           }
       });
  }
}
</script>

<style lang="css">
</style>

我创建了chat-room-picker 什么是下拉菜单,您可以使用它更改聊天室。还有一个chat-room 组件,用于显示当前聊天室的消息。两个组件中都有vue-watch-es 并且新消息被更改,聊天室添加消息(如果消息属于当前聊天室)否则不做任何事情,chat-room-picker 开始闪烁如果消息属于其他房间。

chat-room-picker手表:

  watch : {
    newmessage : function (value) {
      var message = value;
      var picker = $(".chatRoomPicker");
      //TODO: check that the message belongs to current chat room
      picker.addClass("blink");
      picker.on("click", function() {
        picker.removeClass("blink");
      });
    }
  }

聊天室组件的监听部分:

  watch : {
    chatroomid : function (value) { // if chat-room is changed
      this.getChatRoomMessages();
    },
    newmessage : function(value) {  // TODO: here or parent component check the room of the message
      console.debug("newmessage received:" + JSON.stringify(value));
      var msgTmp = value.message;
      msgTmp.user = value.user;

      this.messages.push(msgTmp);
    }
  },

服务器端(在控制器中):

broadcast(new NewMessageEvent($message, $user, $usersOfChatRoom));

而我的NewMessageEventbroadcastOn 方法看起来像这样:

public function broadcastOn()
{
    $channels = [];
    foreach ($this->usersOfChatRoom as $addressee) {
      if($addressee->id != $this->user->id) {
        array_push($channels, new PresenceChannel('chat-' . $addressee->id));
      }
    }
    Log::debug("broadcastOn channels: " . json_encode($channels));
    return $channels;
  //
}

我知道它还没有完成,但我评论了应该在哪里完成代码。

这可能不是最优雅的方式,但它确实有效。如果其他人有其他解决方案,请分享!

【讨论】:

  • 因此,每当您广播 a 的事件时,假设聊天室中有 N 个用户。你广播了N次事件?每次到每个用户的私人频道? 编辑实际上是 n-1 因为发送消息的用户
  • 您好!我更新了我的答案。是的,我愿意。因此,当一个客户端发出一条消息时,它会被发送到服务器,服务器将它广播给聊天室的其他人
  • 谢谢。遇到麻烦是因为我认为应该有更好的方法,但显然广播 N-1 次消息是一种方法。祝你未来好运!
  • 我建议你检查一下 facebook 的 Messenger 页面是如何工作的:www.messenger.com。你有一个 id,我确信你有自己的频道,你的客户正在收听。它给了我这个想法。 :) 我也希望如此!
  • @LakiGeri 整理了一下,延迟在 Redis 的网桥——SocketServer。现在一切正常
猜你喜欢
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
相关资源
最近更新 更多