Firing window.close from within socket.on('disconnect' - node.js

Everyone
I am learning javascript so apologies in advance if my questions is appears ignorant.
I am using sockets to write an on-line interactive quiz app. It is working well. However, I have found that if a users mobile device goes into auto-lock mode then the websocket disconnects, even though when a user touches the device again the screen is still available. I don't want to reconnect a socket, as I am using socket.id to establish an array of online users.
Sorry for the preamble - here is my question. Is there a way to programatically close the window once a websocket is disconnected? Some example code that I have attempted below. This throws an exception:
"ReferenceError: window is not defined"
I know the window. commands works outside of a socket.on function, so assume it cannot be called within.
Anyway, I would welcome any insight, advice and examples on a resolution to help me with my learning.
Many thanks, SJM72
Code extract:
socket.on('disconnect', () => {
const player_name = getUserName(socket.id);
console.log(player_name, " Has decided to leave the session");
window.open('', '_self', ''); window.close();
});

Related

Socket.io send notification only to request initiator?

First of all I'm an OG bare metal Java server side guy. That means I'm new to Docker, Node.js (JavaScript in general), socket.io and trying to learn all these things at once so please pardon me if I've made an obvious mistake. I've been working on a pro-bono project for some time in hope that in exchange I get to learn all of these things and move into the new way of doing things.
Now, having said that, moving along to my question - In the code snippet below (especially the last line)
io.on('connection', function (socket) {
console.log(`connection made from ${socket.id}`);
socket.on('disconnect', function () {
console.log(`connection ${socket.id} closed`);
});
socket.on(DOWNSTREAM_MESSAGE, function (msg) {
//console.log(`Received socket payload: ${msg} from ${socket.id}`);
iopubClient.publish(DOWNSTREAM_MESSAGE, msg);
});
iosubClient.subscribe(UPSTREAM_MESSAGE, message => {
//console.log(`Sending socket payload: ${message} to ${socket.id}`);
socket.emit(UPSTREAM_MESSAGE, message);
});
});
as far as I understand from all the internet sleuthing is that:
io.emit(....
broadcasts to all clients the server socket is connected to, and
socket.emit(....
sends to the call initiator (specifically referring to emit cheat sheet among other sources).
However, with the code snippet above, even when I'm using socket.emit, all subscribing socket.io clients receive the message as if it were a broadcast which isn't what I want. I really do want to send the response back to the io that initiated this particular request.
I've tried almost every way of achieving session stickiness from session stickiness (current implementation an attempt via cookie based stickiness with a HAProxy in front of the service).
In case it helps you help me, full code-base is here.
As I mentioned, I'm learning all of this on the fly so I will not be embarrassed (in fact would be quite thankful!) if you point me to something I'm doing wrong, but for the life of me, I cannot get the response to go only to the request initiator.
Please help?!

Azure Event Grid consume events from Hybrid Connection with Node

Can someone point me in the right direction? I'm working with a client who is looking to have 3rd parties receive event data from them (blob created, etc). The C# example works great:
https://azure.microsoft.com/en-us/resources/samples/event-grid-dotnet-publish-consume-events/
However, some of their clients are using Node and we're having trouble getting them connected. The samples work great when there is a sender/listener, but the listener is effectively swallowing Event Grid events, as they are sent with a "request" key, and the sender/listener events are sent with an "accept" key.
https://github.com/Azure/azure-relay/tree/master/samples/hybrid-connections/node
I can point directly to the line within each Node sample (HybridConnectionWebSocktServer.js, etc.) where the event is being processed, and subsequently ignored.
I've also found and tried this function example, but haven't been successful receiving Event Grid events locally:
https://azure.microsoft.com/is-is/resources/samples/event-grid-node-publish-consume-events/
Is there a better example? Is there a better method? Should we be approaching this from another direction?
Any help, guidance, or nudge in the right direction would be greatly appreciated.
I reached out to all available avenues to try to resolve my issue quickly. I wanted to post the answer here in case anyone else has the same trouble I did.
Huge thanks to those at Microsoft that were able to point me in the right direction and help me solve the issue.
Event Grid is built exclusively on HTTP so it makes sense that you’re getting the events with a request gesture. Incase you haven’t found it, the doc on the interaction model for Hybrid Connections is available here.
The sample you’re looking at uses the hyco-ws package which is for websockets only. The package you want to be using is hyco-https which allows listening to HTTP messages. This sample shows how to use Hybrid Connections with HTTP.
I had tried this example as well, but didn't see (or know how to access) the event data.
A little more digging I was able to find a way to data by adding the req.on lines:
(req, res) => {
console.log('request accepted: ' + req.method + ' on ' + req.url);
req.on('data', function(chunk) {
var bodydata = chunk.toString('utf8');
console.log(bodydata);
});
res.setHeader('Content-Type', 'text/html');
res.end('<html><head><title>Hey!</title></head><body>Relayed Node.js Server!</body></html>');
});
This wrote out the event I was expecting to see to the console.

How to catch when a user leaves the page in Meteor and/or Iron router?

I'm trying to catch when a user leaves from my Meteor application (version 1.2.0.2) ; something equivalent to the SocketIO disconnect() on the server side.
The user could close his browser, go to another website or simply refresh the page and it would fire anyway
Surprisingly, i'm searching on Internet and everything is mixed up, nothing works properly. I thought Meteor was literally based on this magic-live processing so it must manage this event in a way or another.
Iron router documentation specify this :
onStop: Called when the route is stopped, typically right before a new
route is run.
I also found Router.load and Router.unload but none of them work. This is my current [not working] code which is quite simple
Router.configure
layoutTemplate: 'MasterLayout'
loadingTemplate: 'Loading'
notFoundTemplate: 'NotFound'
Router.onStop (->
console.log('Try to stop')
Users.insert({
name: "This is a test"
lat: 0
lng: 0
})
)
Am I doing something wrong here ? How do you catch this event in my app ?
You need to attach to the onStop of the route, not the router. For instance:
Router.route('/', {
onStop: function() {
console.log("someone left the '/' route");
}
});
Another option is to use the onStop event of subscriptions. That is probably the option most similar to the socketio disconnect you mentioned. You can find an example of that in the typhone source code.
There were two solution working, I found the 2nd and best one by searching in the API Documentation for a while.
First solution : working with subscribe & publish
Anywhere in the controller / front-end side you must subscribe to a collection
# in coffee
#subscribe('allTargets')
# in javascript
this.subscribe('allTargets')
Afterwards you just have to publish and add a onStop listener. This example will take a Targets collection I already defined somewhere before, it just gets all the entries.
# in coffee
Meteor.publish 'allTargets', ->
#onStop ->
# Do your stuff here
return Targets.find()
# in javascript
Meteor.publish('allTargets', function() {
this.onStop(function() {
// Do your stuff here
});
return Targets.find();
});
You have to be careful not to return Targets.find() before you set the onStop listener too. I don't think it's a perfect solution since you don't listen to the connection itself but the changes of a collection.
Second solution : working with DDP connection
I realized through the Meteor API Documentation we can directly listen to the connection and see if someone disconnect from the server-side.
To stay well-organized and clean within my Meteor Iron project I added a new file in app/server/connection.coffee and wrote this code
# in coffee
Meteor.onConnection (connection) ->
connection.onClose ->
# Do your stuff
# in javascript
Meteor.onConnection(function(connection) {
connection.onClose(function() {
// Do your stuff
});
});
You can manage datas with connection.id which's the unique identifier of your browser tab. Both solutions are working well for me.
If you use Meteor.userId through their accounts system, you can't use it outside a method in the server-side so I had to find a workaround with the connection.id.
If anyone has a better solution to manage connections while getting this kind of client datas, don't hesitate to give your input.

What is the purpose of `socket.broadcast.to(param)` in socketio

While I'm learning Node.js, I confronted an example to write a chat system.
Somewhere in the code there's following line:
socket.broadcast
.to(message.room)
.emit('message', theMessage);
I don't understand what the to function is doing. Also, I didn't find any clue at the client side code. What happens if the code has not to(message.room) part?
socket.broadcast.to broadcasts to all sockets in the given room, except to the socket on which it was called.
For more details : http://socket.io/docs/server-api/#socket#to(room:string):socket

Async profiling nodejs server to review the code?

We encountered performance problem on our nodejs server holding 100k ip everyday.
Now we want to review the code and find the bottle-neck.
#jfriend00 from what we can see now, the problem seems to be DB access and file access. But we don't know what logic caused this access.
We are still looking for good ways to do the async profiling of nodejs server.
Here's what we tried
Nodetime
This works for us to some extent. It can give the executing time of code specified to the lines. However, we can't locate the error because the server works async and no stacking and calling info can be determined.
Async-profiling
This works with async and is said to be the first of this kind.
Problem is, we've integrated it's js code with our server-side code.
var AsyncProfile = require('async-profile')
AsyncProfile.profile(function () {
///// OUR SERVER-SIDE CODE RESIDES HERE
setTimeout(function () {
// doAsyncStuff
});
});
We can only record the profile of one time of server execution for one request. Can we use this code with things like forever? I've no idea with this.
dtrace
This is too general for us to locate problem in nodejs code.
Do you have any idea on profiling nodejs server code? Any hints or suggestions are appreciated. Thanks.

Resources