I wrote a TCP server using Node.js and on my tests (with Mocha) I'm testing that the server actually emits all the events it should. The one problem that I'm finding is that I cannot trigger the error event at will so I cannot automate this test.
socket.on('error', function()
{
// How do I test this?
});
Is there a way to trigger this event manually? O maybe craft a corrupt packet?
You can emit it manually: socket.emit('error', new Error('foo bar baz'));
Related
I am trying to use socket.io alongside a local event listener within the socket.on("connection", client => {...} ) event. The problem is every time a new socket.io connection is created it's creating a new event listener. This eventually leads to a max listeners error in node.js.
I need that event listener there so it can await data from other parts of the application and then use the returned socket.io client object to emit that data to the connected socket.io client.
Should I simply increase setMaxListeners per the documentation? Or is there something I should be doing differently with my code to prevent the creation of a new event listener each time the client connects (e.g. is there a way to register the event listener globally, but pass and use new client connections into the event listener)?
io.on('connection', client => {
//console.log("Websockets client connected")
events.on("initializePage", data => {
client.emit("initializePage", data)
})
client.on('disconnect', () => {
console.log("Socket.io client disconnected")
})
})
In the snippet of code you present, the global events eventEmitter will have a new listener attached for each new socket. So indeed, after a while the maxListeners will be rapidly exhausted if many clients connect.
A first step to avoid adding listeners indefinitely would be to some clean up each time a client disconnects, by tearing down all the listeners it registered with the off method.
In the case the clients only need to be notified one time, you can decide to register the listener using the once method instead of on, which will do the clean up automatically after one trigger.
But, to get back more specifically to socket.io, I feel you're in the situation when you want to perform some kind of broadcast/multicast. Therefore, what about using the namespace system and call:
events.on("initializePage", data => {
io.sockets.emit("initializePage", data);
})
This code has to be written at the top level of your file, not in the connection handler.
I'm using ws version 7.4.0 and I would want to display a console log or perfom operations between the moment where the client is sending a message to the server and before the server fire the on event message.
To represent it:
webserver.on('example', function callback(msg){console.log(msg);}); //act before the call of callback
client------server---[here]---callback
The only way I see right now would be to use a "root" function before the callback of all my events like this:
function callback(msg){console.log(msg);}
webserver.on('example', function root(msg) {console.log('example msg'); callback(msg);});
I don't know if this is a real and/or good solution I really wish to write a clean and organized application.
If someone could give me some advise or a real solution? Thank you.
You could make a wrapper for all of your callbacks like so:
function makeCallback(fn) {
return function(msg) {
if (!environment.prod) console.log(msg);
fn(msg)
};
}
var myCallback = makeCallback(function (msg) {
// something
});
webserver.on('example', myCallback);
Or I think the better solution is to stream the requets into your stdout although I don't know the implications of using this method.
And I want to address the naming of your websocket server. Even though a web socket server is technically a web server, it only responds to the websocket protocol and naming it webserver could be misleading, I would recommend using the naming like in their documents wss.
I'm working on a custom winston transport; documentation (cut&paste follows) is crystal clear...
class CustomTransport extends Transport {
log(info, callback) {
setImmediate(() => {
this.emit('logged', info);
});
// Perform the writing to the remote service
callback();
}
};
... but, which is the meaning of this.emit('logged', info); and why in a setImmediate?
I would have said that calling the callback was enough to let the caller know that writing operation have been performed,
we could say that setImmediate is required to fire the event after IO handlers in Node.js event loop, but there is absolutely no guarantee that next IO loop is enough for my custom write to be finished, so
why to fire something called 'logged' actually before the write operation rather than fire something called 'logging'?
I asked the same thing to the maintainers, but the result was... tumbleweeds.
Can somebody revel me the secrets behind that mysterious event?
Tired by the silence I did a test with a custom winston transport which does not fire the logged event: I wrote 3GB logs with 30,000,000 logger.info calls and I had no problems, neither the application grown by a single byte of memory usage.
My conclusion is: firing that event is completely useless.
Transports can listen to the logged event.
const transport = new CustomTransport();
transport.on('logged', (info) => {
// Verification that log was called on your transport
console.log(`Logging! It's happening!`, info);
});
If no transports are listening to that event, then it's useless.
I would emit the event just in case anyone is listening.
I checked winston's roadmap and in version 3.3.0 the "logged" event will be emitted automatically by winston-transport.
I am running into a problem while using socket.io to do some event handling. For some reason, the following code snippet does not handle the event 'update', or any event for that matter. Let me explain the situation.
I have created a file named updates.js to create a socket.io socket variable named socket_8888 that is bound to port 8888. I then use module.exports to make that socket variable available to any other file that imports updates.js using require('updates.js'). I structured my application this way because I need to emit events from several different files.
In app.js:
var updates = require('updates.js');
setTimeout(function() {
updates.regular.on("update", function () {
console.log("Updated.");
})
}, 1000);
setTimeout(
function () {
console.log(updates.regular.eventNames()); // Verifying that there is actually a listener bound to the socket -> prints ['update']
updates.regular.emit("update", 100)
}, 1500);
In updates.js:
var io = require("socket.io");
var socket_8888 = io(8888);
var updates = {
regular: socket_8888
};
module.exports = updates;
However, a few simple tests have uncovered that events are not being handled, and I really cannot figure out why. The word "Updated" should print a second and a half after I run the application using "node www", but it does not.
The reason I started doing this simple testing was because I am trying to revive an old website of mine, but after a couple years, API updates have rendered a lot of my code useless. So I am trying to rebuild. I am not trying to send events between different files on the server. I am only testing the events locally because the events were not firing to the browser client. For this reason, I decided to investigate using this simple test, and it turns out the events can not even be emitted/listened to on the actual server, let alone be handled on a client that is on a whole different network.
I have already verified that the listener is actually binding to the socket. However, I do not know how to check whether or not the socket is actually emitting the event "update".
I have written the listener to bind only after one second because attempting to bind the moment the application starts does not give Express enough time to set everything up. Otherwise, the socket would still be undefined.
I do not get any error messages. The code just does not work as I expected.
I would really appreciate it if the community can tell me why the event 'update' is not being handled.
To include update module (update.js)
Try this
It work's Perfectly
module.exports = updates
var updates = require('./updates');
We need to update the client side UI to indicate that a message fails to deliver. How do I have Socket.IO JS client call a custom callback directly when the message fails to deliver? For example, something like:
socket.emit("event", data).onError(myCallback);
I know Socket.IO provides the Ack mechanism to confirm delivery success. Therefore, one can set up a timer with a handler which calls the failure callback, if the ack is not called after a certain amount of time. But this doesn't seem to be the best way to do.
Also there is the error event provided by Socket.IO, but it doesn't come with info regarding which emit caused the error.
Unfortunately there's no way to get errors from callbacks, the only way is to indeed create your own timeout:
var timeoutId = setTimeout(timeoutErrorFn, 500);
var acknCallbackFn = function(err, userData){
clearTimeout(timeoutId)
//manage UserData
}
socket.emit('getUserData', acknCallbackFn);
Source of the code
And there's another issue about this, open
So for the time being you have to stick with your manual setTimeout.