Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing this.$socket from Vuex actions #91

Closed
etcogit opened this issue Jun 13, 2018 · 9 comments
Closed

Accessing this.$socket from Vuex actions #91

etcogit opened this issue Jun 13, 2018 · 9 comments
Labels
question 🤔 Further information is requested

Comments

@etcogit
Copy link

etcogit commented Jun 13, 2018

Hi,

In my project's folder structure I splitted my Vuex actions (and also mutations, getters and state) into separate files, like suggested here.

Here is an example of an action.js file:

export const saveUserLog = ({ commit, rootState }, data) => {
  data.user = rootState.globalModule.userConnected._id
  commit('addUserLogToTempMemory', data)
  this.$socket.emit('saveUserLog', data) // this doesn't work
}

How can I access to the $socket instance from within my action ?

I tried

export const saveUserLog = ({ commit, rootState, Vue }, data) => { // adding Vue here
  data.user = rootState.globalModule.userConnected._id
  commit('addUserLogToTempMemory', data)
  Vue.$socket.emit('saveUserLog', data) // to access from here
}

and like suggested in this post

export const saveUserLog = ({ commit, rootState }, data) => {
  data.user = rootState.globalModule.userConnected._id
  commit('addUserLogToTempMemory', data)
  this._vm.$socket.emit('saveUserLog', data) // doesn't work
}

Can you help me?
Thanks

@probil probil added the question 🤔 Further information is requested label Jun 14, 2018
@probil
Copy link
Owner

probil commented Jun 14, 2018

Hi, @etcogit
I'm glad to see an issue from you again. 👍

Currently there few approaches.

  1. Put socket.io instance to the separate file and import it in your actions or any other place of your app. For example:
// --- file: socket-instance.js --- //
import io from 'socket.io-client';

export default io('http://socketserver.com:1923'); // <-- use your socket server here and configuration
// --- file: main.js  --- //
import VueSocketio from 'vue-socket.io-extended';
import $socket from './socket-instance';

Vue.use(VueSocketio, $socket);
// --- file: store/showcase/actions.js  --- //
import $socket from './socket-instance'; //

export const saveUserLog = ({ commit, rootState }, data) => {
  data.user = rootState.globalModule.userConnected._id
  commit('addUserLogToTempMemory', data)
  $socket.emit('saveUserLog', data) // this doesn't work
}
  1. You common function for actions instead of arrow function. Because this in arrow function is not what we actually need. Vuex can't bind vuex module as this if arrow function is used. E.g. this should work:
export function saveUserLog ({ commit, rootState }, data) {
  data.user = rootState.globalModule.userConnected._id
  commit('addUserLogToTempMemory', data)
  this._vm.$socket.emit('saveUserLog', data) // doesn't work
}

Those approaches i not perfect. Currently I'm trying to figure out how to make socket usage in actions simplier. If someone has any idea I will be glad to hear and discuss. 🤝

@etcogit let me know if that helped you.

@probil
Copy link
Owner

probil commented Jun 20, 2018

Closing because of inactivity

@probil probil closed this as completed Jun 20, 2018
@xino1010
Copy link

xino1010 commented Dec 5, 2018

Thanks @probil

@douira
Copy link

douira commented Mar 5, 2019

I've seen other WebSocket libraries solve this problem by putting the socket instance on the global Vue object something like this: Vue.$socket.
Is this still even a problem or is has this already been solved with something like Vue.$socket?

@quietcoolwu
Copy link

quietcoolwu commented Mar 7, 2019

@probil I wonder how can we set a header for auth, on the connection of socket instance (and not in the static config of instance), here's my instance config

export default io(
  `${location.protocol}//${location.hostname}:${API_PORT}/${namespace}`,
  {
    path: '/socket_io_api',
    // disable auto-connect to bind connect/disconnect with user xhr login/logout
    autoConnect: false,
    transportOptions: {
      polling: {
        extraHeaders: {
          Authorization: `JWT ${localStorage.authToken}`,
        },
      },
    },
  });

Seems that headers must be fixed and can't update with variable, , and now it will just send sth like JWT undefined in handshaking because localStorage.authToken === undefined when we define the socket.io instance, and localStorage.authToken will only be updated to a valid token after user login auth finished.

@douira
Copy link

douira commented Mar 7, 2019

Seems that headers must be fixed and can't update with variable, , and now it will just send sth like JWT undefined in handshaking because localStorage.authToken === undefined when we define the socket.io instance, and localStorage.authToken will only be updated to a valid token after user login auth finished.

You're not updating the Authorization field here at all though. Once the file has been run, the field will not change because the code is only run once on import.

@quietcoolwu
Copy link

@douira does that mean I cannot check the socket.io connection for auth on the serverside for all? My target is to check each client connection handshake from the headers.

@douira
Copy link

douira commented Mar 8, 2019 via email

@quietcoolwu
Copy link

quietcoolwu commented Mar 24, 2019

@probil @douira
could you gimme a specific example on how to use an event handler for token auth?
If I import $socket from an outer instance which is kind of pre-configuired, how can I get the header via localStorage or vuex getters, which may vary and add the header to this instance? and which event should I bind the auth procedure?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question 🤔 Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants