Socket.io's examples all follow this pattern
io.sockets.on("connection", function(mySocket){
mySocket.on("my message", function(myData){
...
});
});
It seems to me that this would create a new callback function for every connection. Assuming that every socket responds to the message in the same way, wouldn't it be more memory efficient to define the handler once for all sockets like this:
function myMessageHandler(data){
...
}
io.sockets.on("connection", function(mySocket){
mySocket.on("my message", myMessageHandler);
});
or even this:
io.sockets.on("my message", function(mySocket, myData){
...
});
If so, why would Socket.io recommend a practice that wastes memory? Are we expected to want to keep stateful variables for the socket inside the "connection" callback's closure?
Looking at it from another perspective, the first form is easy to read (because so many details are left out). I think this form best illustrates how the library works. Similar style is used on the Node website itself for the same reason, I believe. And I think that's precisely why it is used in those places.
After a few minutes reading blogs and discussions suggests that developers are usually opting for passing around named functions. Although I'm sure there's a performance gain in it, the primary motivation is no doubt readability. I think you'll find the second form (or a more drawn out form) to be easier to work with as your functions grow.
Defining Socket.io in most efficient way:
io.on('connection', function (socket) {
socket.on('new-message', function (data) {
io.emit('emit-message', data)
});
});
Or
io.on('connection', (socket) => {
console.log('user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
Related
Because Node runs the code inside a require call and then exports the members defined in it, it seems like it would be better to define functions outside of functions when that module is required or used multiple times.
For instance, take the following two codes using express:
router.get('/', function (req, res) {
function logTest () {
console.log('log test');
}
});
And
function logTest () {
console.log('log test');
}
router.get('/', function (req, res) {
logTest () {
});
It seems like the code in the second answer would be more efficient because logTest is only defined one time as opposed to being defined every time a get request is made. Is this true? Are there any best practices about where to define these functions?
I have looked around other answers and not found anything that really gets to my question here.
EDIT:
In addition to performance gains, (for which, in Node, the answer seems to be little to none) I am interested in style / maintainability and if one technique is preferred to the other in this respect.
Thank you
There's more than one node.js tutorial out there, demonstrating how to create a server. But, they're coded in different ways. So, how do you know when to write it one way, versus another? None of the tutorials explain why they wrote it the way they did.
For example...
Example 1:
// Create an http server, passing in a function for some reason:
http.createServer(function(request, response) {
versus Example 2:
// Create an http server, and then start it
var server = http.createServer(handleRequest);
server.listen(PORT, function () {
Thanks in advance. I'm really having trouble understanding this.
They're no different, really. In the first, you're defining the function for handling a request on the spot then have to start listening at the end.
http.createServer(function(request, response) {
...
}).listen(PORT, function() { ... });
In the second, you define the function for handling a request elsewhere and don't use chaining.
function handleRequest(request, response) {
...
}
var server = http.createServer(handleRequest);
server.listen(PORT, function() { ... });
They both do the same thing. It just depends on how you want to write it.
Preference really.
Some prefer to handle the function definition within the argument list (typical of the older documentation as well) while others prefer to pass in the name of an already defined function.
I find the second example easier to maintain and more flexible but it really boils down to preference.
I want to establish a two-way (bidirectional) communication within my meteor app. But I need to do it without using mongo collections.
So can pub/sub be used for arbitrary in-memory objects?
Is there a better, faster, or lower-level way? Performance is my top concern.
Thanks.
Yes, pub/sub can be used for arbitrary objects. Meteor’s docs even provide an example:
// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
var self = this;
check(roomId, String);
var count = 0;
var initializing = true;
// observeChanges only returns after the initial `added` callbacks
// have run. Until then, we don't want to send a lot of
// `self.changed()` messages - hence tracking the
// `initializing` state.
var handle = Messages.find({roomId: roomId}).observeChanges({
added: function (id) {
count++;
if (!initializing)
self.changed("counts", roomId, {count: count});
},
removed: function (id) {
count--;
self.changed("counts", roomId, {count: count});
}
// don't care about changed
});
// Instead, we'll send one `self.added()` message right after
// observeChanges has returned, and mark the subscription as
// ready.
initializing = false;
self.added("counts", roomId, {count: count});
self.ready();
// Stop observing the cursor when client unsubs.
// Stopping a subscription automatically takes
// care of sending the client any removed messages.
self.onStop(function () {
handle.stop();
});
});
// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");
// client: subscribe to the count for the current room
Tracker.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
// client: use the new collection
console.log("Current room has " +
Counts.findOne(Session.get("roomId")).count +
" messages.");
In this example, counts-by-room is publishing an arbitrary object created from data returned from Messages.find(), but you could just as easily get your source data elsewhere and publish it in the same way. You just need to provide the same added and removed callbacks like the example here.
You’ll notice that on the client there’s a collection called counts, but this is purely in-memory on the client; it’s not saved in MongoDB. I think this is necessary to use pub/sub.
If you want to avoid even an in-memory-only collection, you should look at Meteor.call. You could create a Meteor.method like getCountsByRoom(roomId) and call it from the client like Meteor.call('getCountsByRoom', 123) and the method will execute on the server and return its response. This is more the traditional Ajax way of doing things, and you lose all of Meteor’s reactivity.
Just to add another easy solution. You can pass connection: null to your Collection instantiation on your server. Even though this is not well-documented, but I heard from the meteor folks that this makes the collection in-memory.
Here's an example code posted by Emily Stark a year ago:
if (Meteor.isClient) {
Test = new Meteor.Collection("test");
Meteor.subscribe("testsub");
}
if (Meteor.isServer) {
Test = new Meteor.Collection("test", { connection: null });
Meteor.publish("testsub", function () {
return Test.find();
});
Test.insert({ foo: "bar" });
Test.insert({ foo: "baz" });
}
Edit
This should go under comment but I found it could be too long for it so I post as an answer. Or perhaps I misunderstood your question?
I wonder why you are against mongo. I somehow find it a good match with Meteor.
Anyway, everyone's use case can be different and your idea is doable but not with some serious hacks.
if you look at Meteor source code, you can find tools/run-mongo.js, it's where Meteor talks to mongo, you may tweak or implement your adaptor to work with your in-memory objects.
Another approach I can think of, will be to wrap your in-memory objects and write a database logic/layer to intercept existing mongo database communications (default port on 27017), you have to take care of all system environment variables like MONGO_URL etc. to make it work properly.
Final approach is wait until Meteor officially supports other databases like Redis.
Hope this helps.
Decided to test out Meteor JS today to see if I would be interested in building my next project with it and decided to start out with the Deps library.
To get something up extremely quick to test this feature out, I am using the 500px API to simulate changes. After reading through the docs quickly, I thought I would have a working example of it on my local box.
The function seems to only autorun once which is not how it is suppose to be working based on my initial understanding of this feature in Meteor.
Any advice would be greatly appreciated. Thanks in advance.
if (Meteor.isClient) {
var Api500px = {
dep: new Deps.Dependency,
get: function () {
this.dep.depend();
return Session.get('photos');
},
set: function (res) {
Session.set('photos', res.data.photos);
this.dep.changed();
}
};
Deps.autorun(function () {
Api500px.get();
Meteor.call('fetchPhotos', function (err, res) {
if (!err) Api500px.set(res);
else console.log(err);
});
});
Template.photos.photos = function () {
return Api500px.get();
};
}
if (Meteor.isServer) {
Meteor.methods({
fetchPhotos: function () {
var url = 'https://api.500px.com/v1/photos';
return HTTP.call('GET', url, {
params: {
consumer_key: 'my_consumer_key_here',
feature: 'fresh_today',
image_size: 2,
rpp: 24
}
});
}
});
}
Welcome to Meteor! A couple of things to point out before the actual answer...
Session variables have reactivity built in, so you don't need to use the Deps package to add Deps.Dependency properties when you're using them. This isn't to suggest you shouldn't roll your own reactive objects like this, but if you do so then its get and set functions should return and update a normal javascript property of the object (like value, for example), rather than a Session variable, with the reactivity being provided by the depend and changed methods of the dep property. The alternative would be to just use the Session variables directly and not bother with the Api500px object at all.
It's not clear to me what you're trying to achieve reactively here - apologies if it should be. Are you intending to repeatedly run fetchPhotos in an infinite loop, such that every time a result is returned the function gets called again? If so, it's really not the best way to do things - it would be much better to subscribe to a server publication (using Meteor.subscribe and Meteor.publish), get this publication function to run the API call with whatever the required regularity, and then publish the results to the client. That would dramatically reduce client-server communication with the same net result.
Having said all that, why would it only be running once? The two possible explanations that spring to mind would be that an error is being returned (and thus Api500px.set is never called), or the fact that a Session.set call doesn't actually fire a dependency changed event if the new value is the same as the existing value. However, in the latter case I would still expect your function to run repeatedly as you have your own depend and changed structure surrounding the Session variable, which does not implement that self-limiting logic, so having Api500px.get in the autorun should mean that it reruns when Api500px.set returns even if the Session.set inside it isn't actually doing anything. If it's not the former diagnosis then I'd just log everything in sight and the answer should present itself.
I'm currently working with Node.js, and have built a socket that accepts data. I am attempting to process the data in a streaming fashion, meaning that I process the data (nearly) as quickly as I receive it. There is a rather significant bottleneck in my code, however, that is preventing me from processing as quickly as I'd like.
I've distilled the problem into the code below, removing the extraneous information, but it captures my issue well enough:
require('net').createServer(function (socket) {
var foo = [];
socket.on('data', function (data) {
foo.push(data); // Accessing 'foo' causes a bottle neck
});
}).listen(8080);
Changing the code in the data event, improves performance considerably:
var tmpFoo = foo;
tmpFoo.push(data);
// Do work on tmpFoo
The problem is, I eventually need to access the global (?) variable (to save information for the next data event); incurring the performance penalty along with it. I'd much prefer to process the data as I receive it, but there does not appear to be any guarantee that it will be a "complete" message, so I'm required to buffer.
So my questions:
Is there a better way to localize the variable, and limit the performance hit?
Is there a better way to process the data in a streaming fashion?
dont use anonyme functions like that:
createServer(function (socket) {
Define functions seperately and call these as follow:
var foo = [];
function createMyServer(socket) {
socket.on('data', reveiveDataFromSocket);
}
function reveiveDataFromSocket(data) {
foo.push(data);
}
require('net').createServer(createMyServer).listen(8080);