MQTT.js how to hook connected status with vuex - javascript

Am still learning vuex, i have a 3 export method connect to mqtt broker with call backs to console out.
The thing after page refresh the client disconnect and client.on("end/disconnect") is not fired.
was thinking if there was a way from software design perspective of view, on how to implement it with vuex to track client connection status and act accordingly.
EDIT:
here is my current code.
export let client = null
export var status = 'initial'
export var startSub = ({username, password}) => {
client = mqtt.connect("ws://192.168.1.30:9001/mqtt",{
clientId: `mqttjs_ + ${Math.random().toString(16).substr(2, 8)}`,
username: username,
password: password
})
client.on("connect", () => {
status = client.connected
client.subscribe('hello/#')
console.log("startSub,Subsecribed")
}).on('error', err => {
status = client.connected
console.log("error", err)
client.end()
}).on("message", (topic, message) => {
status = client.connected
console.log(`topic, ${topic}, msg:: ${JSON.parse(message)}`);
})
//on disconnect call bacl
client.on("disconnect", (packet)=>{
status = client.connected
console.log('client of discconect call back', packet)
})
//on disconnect call bacl
client.on("end", function () {
console.log('client of end call back')
})
}
now when the page refresh the client automatically disconnect.
on my vuex store, if i import status, as state, its useless to track because after refresh its always initial. to be more clear my aim is to after refresh to keep the connection active without it being disconnected.

Related

How to listen to custom event dispatched by third party library in VUE JS

I am implementing agora chat in vue js where there is object which emits 6 events. How can I listen to those in VUE JS. Here is its code in core javascript:
this.agora.conn = new AC.connection({
appKey: this.agora.appKey,
});
this.agora.conn.addEventHandler("connection&message", {
// Occurs when the app is connected to Agora Chat.
onConnected: () => {
console.log("App connected.");
},
// Occurs when the app is disconnected from Agora Chat.
onDisconnected: () => {
console.log("App disconnected.")
},
// Occurs when a text message is received.
onTextMessage: (message) => {
console.log("Message Recieved: ",message);
},
// Occurs when the token is about to expire.
onTokenWillExpire: (params) => {
console.log("Token is about to expire. ",params)
this.refreshToken(this.agora.username, this.agora.password);
},
// Occurs when the token has expired. You need to get a token from your app server to log in to Agora Chat.
onTokenExpired: (params) => {
console.log("Token is expired. ",params)
this.refreshToken(this.agora.username, this.agora.password);
},
onError: (error) => {
console.log("on error: ", error);
},
});
Here agora is the data member in the component and this above code is in mounted hook.
I have noticed console the SDK is dispatching the events but this listener is not catching any. Here is agora data member:
agora : {
baseUrl : "https://a41.chat.agora.io",
appKey : "******",
username : "fana",
password: "123",
conn : null
}

problem with emit from socket.io (server to client)

I'm having a problem with socket.io at the moment I try to send a second time from the server to the client
here is the server code with express and socket.io
io.on('connection', async function (socket) {
let socketId = socket.id;
const mta = new Client("20.64.24.144", 22005, "*", "*");
mta.resources.evokestats.getPlayerCount()
.then((result) => {
console.log("result", result);
socket.emit("players-start", { players: result })
})
.catch((err) => {
console.error(`Ooops! Something went wrong ${err}`);
});
app.post('/player_connect', async function (req, res) {
let ip = req.body[0];
let player = await players.findOne({ ip: ip })
if (player) {
await socket.emit("players", { players: req.body[1] })
} else {
try {
player = await players.create({ ip: ip, name: req.body[2] })
await socket.emit("players", { players: req.body[1] })
await socket.emit("last_24_players", { players: 1 });
} catch (error) {
console.log("error", error)
}
}
res.send("connected")
});
});
and here is my client with reactjs and socket.io
useEffect(() => {
getStats();
}, [])
async function getStats(params) {
socket.on("players-start", function (data) {
setNowPlayers(data.players)
});
socket.on("players", function (data) {
console.log("players", data)
setNowPlayers(data.players)
});});
And in my client using react, in useEffect I listen to the "players-start" and the "players" that was emit.
players-start: It is for every first time that I enter my client he only calls once, to bring all players connected
players: Every time someone connects to the game server, a post call is made to my server where I use the express with socket, in the url '/player_connect' and then immediately emit
The problem: whenever I issue an issue on 'players-start' and then immediately enter the game server that calls the url '/player_connect' it is not triggering the issue of 'players' or at least the client is not receiving.
Test I've done:
My first attempt was to stick everything to the listener "players" but it still doesn’t work
I really appreciate everyone's help.

How to close socket connection for GraphQL subscription in Apollo

I have GraphQL Subscriptions on my Apollo server that I want to close after the user logs out. The initial question is whether we should close this (socket) connections on the client side or in the backend.
On the front-end, I am using Angular with Apollo Client and I handle GraphQL subscriptions by extending the Subscription class from apollo-angular. I am able to close the subscription channels with a typical takeUntil rxjs implementation:
this.userSubscription
.subscribe()
.pipe(takeUntil(this.subscriptionDestroyed$))
.subscribe(
({ data }) => {
// logic goes here
},
(error) => {
// error handling
}
);
However, this does not close the websocket on the server, which If I'm right, will result in a subscription memory leak.
The way the Apollo Server (and express) is set up for subscriptions is as follows:
const server = new ApolloServer({
typeDefs,
resolvers,
subscriptions: {
onConnect: (connectionParams, webSocket, context) => {
console.log('on connect');
const payload = getAuthPayload(connectionParams.accessToken);
if (payload instanceof Error) {
webSocket.close();
}
return { user: payload };
},
onDisconnect: (webSocket, context) => {
console.log('on Disconnect');
}
},
context: ({ req, res, connection }) => {
if (connection) {
// set up context for subscriptions...
} else {
// set up context for Queries, Mutations...
}
When the client registers a new GraphQL subscription, I always get to see console.log('on connect'); on the server logs, but I never see console.log('on Disconnect'); unless I close the front-end application.
I haven't seen any example on how to close the websocket for subscriptions with Apollo. I mainly want to do this to complete a Logout implementation.
Am I missing something here? Thanks in advance!
I based my solution based on this post
Essentially, the way we created the Subscription with sockets was using subscriptions-transport-ws
export const webSocketClient: SubscriptionClient = new
SubscriptionClient(
`${environment.WS_BASE_URL}/graphql`,
{
reconnect: true,
lazy: true,
inactivityTimeout: 3000,
connectionParams: () => ({
params: getParams()
})
}
);
As specified in the question, I wanted to unsubscribe all channels and close the subscription socket connection before logout of the user. We do this by using the webSocketClient SubscriptionClient in the logout function and call:
webSocketClient.unsubscribeAll();
webSocketClient.close();

RabbitMQ Node JS Validate User ID

I use RabbitMQ, SocketIO and MongoDB to make private messages for my app.
The plan is when new user register, app make new unique RabbitMQ Queue for that user, with that user is able to get messages when it is offline. So user send message through SocketIO and it is passed to RabbitMQ Publisher and then when consumer is online he get that message.
My questions now is how to set Validate User ID from sendToQueue (Publisher) function to be able later to read sender ID from consume function?
amqp.connect(CONN_URL, function(err, conn) {
conn.createChannel(function(err, channel) {
ch = channel;
console.log("RabbitMQ channel created...");
});
});
const publishToQueue = async (queueName, data) => {
ch.sendToQueue(queueName, Buffer.from(data.message));
};
const consumeToQueue = async queueName => {
ch.consume(
queueName,
function(msg) {
return msg.content.toString();
},
{ noAck: true }
);
};
I worked out...
const publishToQueue = async (queueName, data) => {
let properties = { headers: {userId: data.to }, timestamp: Date.now() };
ch.sendToQueue(queueName, Buffer.from(data.message), properties);
};
This will send headers with userId information and also timestamp of message

SocketIO ReactJS - socket.io doesn't displays console.log()

I'm working on SocketIO with ReactJS vie a chat app.
When emitting message to my server my client doesn't receive the response of my server. The console.log controlling the mechanism is never displayed.
I can't figure out why since I follow exactly the SocketIO blueprint.
here my client.js :
send= (e) => {
e.preventDefault();
const socket= io.connect(this.state.endpoint);
socket.emit("message", () => {
message: "hey !"
})
console.log("send ended")
}
componentDidMount(){
const socket= io.connect(this.state.endpoint);
socket.on("new_message", (message) => {
console.log("new message ", message)
})
socket.on("user_connected", (message) => {
console.log(message)
})
}
here my server.js :
client.on("message", (message) => {
client.emit("new_message", message)
})
Any hint would be great,
Thanks
The reason for your problem is that you essentially have multiple instances of socket connections created over the life span of your client component.
From the server's perspective, the "new_message" is being emitted to the socket that you created in your components send arrow function. Because that socket instance does not listen to "new_message", you're therefore not going to see the expected log messages in the console.
Perhaps you could consider refactoring your client component code like this, to connect a single socket, and use that as a single means of sending and listening to messages from the server?
class YourComponent extends Component {
// Add socket field to component class
socket : ''
// Note that the send method is not an arrow function here, so
// care should be taken to consider how you invoke send() if
// your current implementation relies on this being an arrow function
function send(e) {
e.preventDefault();
const socket = this.state.socket // UPDATE: Access socket via state
// Send messages to server via the same socket instance of this class
if(socket) {
socket.emit("message", () => {
message: "hey !"
})
console.log("send ended")
}
}
function componentDidMount(){
const socket = io.connect(this.state.endpoint)
socket.on("new_message", (message) => {
console.log("new message ", message)
})
socket.on("user_connected", (message) => {
console.log(message)
})
// UPDATE: Connect the socket, and hold a reference for reuse by the component class
// instance via the component's state (seeing you can't add a class field for this)
this.setState({ socket : socket })
}
}

Categories

Resources