javascript monitoring numerous socket channels for echoes

Currently, I am in the process of developing a chat application. On the server side, I am utilizing: php, laravel 5.4, and pusher. On the client side, I have incorporated vue.js along with laravel-echo.

Initially, I successfully created a "public chat room" which is essentially a chat group. My current focus lies in implementing private chat rooms.

My inquiry: What would be the most efficient approach (on the client side) to monitor all channels associated with the rooms that the user is part of?

End goal: To ensure that every channel within private and public rooms is monitored, similar to the functionality seen on the Facebook Messenger web page.

At this point, within the chat-window component, this is what I have:

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
          });
      });
  }
});

However, this setup only listens to the chatroom channel. How can the client listen to all the chatrooms stored in this.chatRooms ?

Appreciate any insights provided!

Answer №1

After realizing that each user needs to have their own channel, I made adjustments to my chat-window component:

<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 received message is from the picked chat room
             console.debug("received message is from the picked chat room!");
             this.newmessage = e;
           } else { // if the received message is not from the picked chat room
             this.newmessage = e;
           }
       });
  }
}
</script>

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

I introduced a chat-room-picker, which is a dropdown for changing chatrooms, and a chat-room component for displaying messages in the current chat room. Both components utilize vue-watch to handle new messages - adding them to the chat room only if they belong to the current room, otherwise performing no action. The chat-room-picker will start blinking if the message belongs to a different room.

chat-room-picker watch:

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

Watch part of the chat-room component:

  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("new message received:" + JSON.stringify(value));
      var msgTmp = value.message;
      msgTmp.user = value.user;

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

On the server side (in controller):

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

The broadcastOn method of the NewMessageEvent looks like this:

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;
  //
}

While it's not a fully complete solution, I have indicated where the code needs to be finalized. It may not be the most elegant approach, but it gets the job done. If anyone has alternative solutions, please feel free to share!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript: Searching for multiple parameters is not possible - when using asynchronous functions, only the first parameter is returned

I've been struggling with this issue for a whole day now: I'm working on a website where I can input contacts into a SQLite database. My goal is to be able to query the database by either studentID or last name (nachname in German). I have an API ...

Experience a dynamic D3 geometric zoom effect when there is no SVG element directly underneath the cursor

Currently, I am working on incorporating a geometric zoom feature into my project. You can see an example of what I'm trying to achieve in this demo. One issue I've encountered is that when the cursor hovers over a white area outside of the gree ...

npm encountered an error due to conflicting peer dependency of version 1.0.0

I'm baffled by this persistent error. I've been attempting to set up a fresh react-native project alongside an existing one in a separate directory that is not nested lower than the original installation. Despite uninstalling and reinstalling Nod ...

Retrieving Value from Dynamic Content Using jQuery `.keypress()` and `.delegate()`

I have encountered an issue with my code that is unable to retrieve the value of a specific ID on the .keypress function after using .delegate. The ID and other contents are generated dynamically through an AJAX call. $(document).delegate('.edit_ ...

When hovering over a select option, a description and clickable link will be displayed

I need to display a description with a clickable link when hovering over any option in the select tag. <div class="col-lg-4"> <div class="form-group"> <label class="form-label">Goal</label> <select name="semiTaskType ...

Utilizing Nuxt 3 server as a passthrough API along with FormData for concealing external endpoints

I'm currently grappling with understanding the Nuxt/server API and am struggling to figure out how to properly send a POST request with form-data (specifically files) to the Nuxt server in order to forward it to an external service: Within my pages.v ...

Angular 2 event emitter falling behind schedule

I am currently utilizing Angular 2 beta 6. The custom event I created is not being captured import {Component, OnInit, EventEmitter} from 'angular2/core'; import {NgForm} from 'angular2/common'; import {Output} from "angular2/core" ...

encountering an error of unsupported grant type while attempting to authenticate a user

I've seen a lot of discussions on this topic, but none have addressed my specific issue. Currently, I am working on an angular 5 application and trying to retrieve an authentication token by sending a post request to a server. Testing the connection ...

Encountering difficulties accessing Node.JS Sessions

Hey there, I am currently working on integrating an angular application with Node.js as the backend. I have set up sessions in Angular JS and created my own factory for managing this. Additionally, I am utilizing socket.io in my Node.js server and handling ...

Steps for displaying a website within a specific Div using HTML

I'm trying to set up a website to open within a specific <div> tag, like the example shown in this link: Responsive. Can anyone spot what I'm doing incorrectly? <html> <head> <script> function mobile320() { ...

Leveraging glob in Yarn/NPM commands

Currently, I am utilizing a script to execute multiple files using Node.js with a glob pattern to capture the files: node build/**/*.spec.js Although this method seems to be functioning correctly, when I insert the same command into the scripts object as ...

Setting up NextJS on Dokku for a Production Environment

I have successfully installed Dokku and am ready to deploy my basic NextJs application on it. However, I am facing an issue where the application is running in development mode instead of production mode. When I check the value of the NODE_ENV variable in ...

What is the easiest way to retrieve a basic date with the month represented by a numerical

Struggling to retrieve the date in the format "Oct 29". I attempted using split but it varies every day. This is what I've come up with so far. let currentDate = new Date().toLocaleDateString('en-US', { month: 'short', day: 'n ...

In Node.js and Postgresql, encountering the error "Trying to access a property that is undefined" is common and can be frustrating

const pool = new pg.Pool(config); var tablename = req.body.tablename; pool.connect(function (err, client, done) { var query_get_value = 'SELECT * FROM '+ tablename; client.query(query_get_value, function (err, result) { d ...

Creating a tree-view in Vue.js that includes clickable components which trigger a Vue.js modal to open up

I have a unique requirement to implement a tree-view feature in Vue-JS for displaying JSON data. However, I need to enhance this by triggering a VueJS modal when any of the data fields in the JSON view are clicked. I have explored various npm modules that ...

Unable to deactivate button within component using setState is ineffective

Once the button within the RecipeListItem component is clicked and the handleFavorites function has been triggered, I want the button to become DISABLED. What am I missing in my logic? Because this code isn't functioning as expected... Child compone ...

What's the best way to set up multiple NestJS providers using information from a JSON file?

Recently diving into NestJS, I am in the process of building an application following the MVC architecture with multiple modules including: Project | +-- App.Controller +-- App.Service +-- App.Module | +-- SubModule1 | | | +-- SubModule1.C ...

Having trouble installing npm packages after upgrading to macOS Big Sur

Since upgrading to macOS Big Sur, I've encountered an issue where I cannot run npm install with npm versions older than 7. Whenever I attempt this, I receive the error message "Maximum call stack size exceeded", even on a clean project folder (without ...

I am facing issues with my npm scripts, they are not functioning properly even after I reinstalled the packages listed

As part of my work, I have created a specialized build system for front-end developers using npm scripts and configuring various tasks in the scripts section of the package.json file. These tasks cover common activities like minifying CSS, linting code, ge ...

Design the parent element according to the child elements

I'm currently working on a timeline project and I am facing an issue with combining different border styles for specific event times. The main challenge is to have a solid border for most of the timeline events, except for a few instances that share a ...