If I create a server using this code:
var net = require('net');
server = net.createServer(function(sock){
/** some code here **/
});
server.listen(9000);
How do I access the socket outside of the callback function? This would help me to be able to create an array/list of sockets that I can store and access whenever I need to send data to a specific client.
I did have a weird workaround that I am currently using but I don't think this is the correct way. Basically I added socket to the server object by saying:
this.socket = sock
inside the callback function of createServer.
Then I can access it saying server.socket but this is only really useful if there is only one client.
To help better understand what I am trying to accomplish I have created a class that has a constructor function which holds this code:
this.server = net.createServer(this.handleConnection)
This class also has the method handleConnection to use as the callback. I also have a method called start which can be called with a port as a parameter to initiate server.listen(port).
What I want to accomplish is a method like below:
sendCommand(message, socket){
socket.write(message);
}
This way the server can send a message to the client from a function that is not within the callback function of createServer. Keep in mind that I am doing this from within a class so using the this keyword within the callback function accesses the net server object and not the class I created.
Every example I see is an extremely simple tcp server that only has one message sent from the server within the callback function. If anyone could shed some light on my problem that would be great thanks!
I'm not sure if this is what you're after, but I would do something like this.
var net = require('net');
var conns = [];
var server = net.createServer(function(sock){
conns.push(sock);
sock.on('close', function (){
// TODO: Remove from conns
});
});
server.listen(9000);
var net = require('net');
var listeners = [];
server = net.createServer(function(sock){
/** some code here **/
listeners.push(sock);
sock.on('close', function (){
var index = listeners.indexOf(sock);
if (index > -1) {
listeners.splice(index, 1);
}
});
});
server.listen(9000);
Related
Apologies if this is a duplicate, I searched the internet for hours and came up empty so I decided to post here.
I am developing a module for node.js that would have to deal with socket connections. I want to create a function that returns an object to the user that will then receive events the user can set listeners on. However, I want to do it in a way so that the user wont be able to emit events on that object. Instead, I want the emit function in my event emitter to be overwritten by my own function.
Basically, I want to return an object that receives events and has a function called "emit" that acts like any regular function.
Heres a small example of what I have in mind:
var events = require('events');
var out = (function(){
var obj = new events.EventEmitter();
// I used nextTick to emulate the asyncrounes nature of the socket server
process.nextTick(function(){
obj.emit('Message', "Dummy socket message") // This will be triggered when a message is sent to the socket server
})
return obj;
})();
out.on('Message', function(msg){
console.log(msg)
out.emit("newWork", "New instructions")
// Im trying to make it work so that this would not throw the event emitter into an infinite loop
});
Now, in the out.on("Message", function... part I want the user to be able to write out.emit("dummy", "dummy data") and be able to call my own emit function that does something with the provided inputs.
How would I go about doing that?
I know it must be possible somehow since socket.io does exactly that.
Heres a small piece of code with socket.io
socket.on('test', function(){
console.log("called!")
})
socket.emit("test")
When I run that, it doesnt trigger itself. The emit function seems to be overwritten by something else but the socket object still receives events that are emitted from within somehow.
I hope that my explanation was sufficient.
Thanks in advance!
Edit: I know that using (function() { ... })() is not the way to create modules. Im using here just to make it easier to illustrate as the concept stays the same with this approach
I think I figured it out on my own.
I will overwrite the emit function in the new EventEmitter instance that I create with my own function and use the one from EventEmitter.prototype instead. That way I can ship my object back to the user with a custom emit function while still being able to emit events on that object from my module
Here's a small demo I wrote while trying to figure this out.
var events = require('events').EventEmitter;
obj = new events();
obj.emit = function(name, data){
console.log("Received: name - " + name + "; data - " + data);
}
function emitOnObj(obj, name, msg){
events.prototype.emit.call(obj, name, msg);
}
This looks pretty good to me but if there's a better way to do this then Im all ears :)
I've just started learning node.js and express and there's something that confuses me a bit in the "hello world" example on the express.js website. In the example, they refer to the server variable inside the callback function.
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('App listening at http://%s:%s', host, port);
});
Does app.listen() return a value to server variable before it executes the callback function? How can it do that and how does it work? Is this the same for all callback functions in node (and javascript)?
I would just like a simple explanation of the execution process.
To be clear, I understand that the callback function has access to the server variable. But if the app.listen method executes the callback function before it returns a value to the server variable, wouldn't that mean that the server variable is still underfined when you try to access server.adress()? That is what I don't understand.
Does app.listen() return a value to server variable before it executes the callback function?
Yes, exactly. app.listen() resembles to the plain Node.js server.listen method.
The callback is an shortcut for assigning the server an listener to the listening event.
You could do the same with the following code:
var server = app.listen( 3000 );
server.on( "listening", function () {
console.log( "server is listening in port 3000" );
});
How can it do that and how does it work? Is this the same for all callback functions in node (and javascript)?
This happens because IO events in Node.js are all run asynchronously (with exceptions from the fs module) - this is, they will only take place when other synchronous code have finished to run.
This works the same in browser JS - if you run some JS process synchronously, any events triggered (like click, blur, etc) will only execute after that one finishes.
A function has access to all the variables that existed in the scope where it was created (unless it masks them).
var in_the_global_scope = 1;
function outer() {
function inner() {
alert(in_the_global_scope);
}
inner();
}
inner has access to any variable declared in inner, outer and the global scope.
A function being a callback isn't really relevant.
The listen method itself doesn't have access to server because listen was created in a different scope.
But if it returns a value, how can it then execute the callback function?
Because it doesn't just execute the callback. It waits for an event and the callback gets fired in reaction to that.
var timeOutId = setTimeout(function() {
alert(timeOutId);
}, 1000);
var server is being assigned to the function app.listen()
If you look at the express documentation it states that
The app.listen() method is a convenience method for the following (for HTTP only):
app.listen = function() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
By setting var server = app.listen() and the fact that app.listen() returns something, you're essentially setting var server to whatever app.listen() return.
You can thinking like that, the app.listen() return an object server which include information of how to run the server, example port, address, like a paper of instructions. Then it go to run server.
When server was run, the application also add some remark on that instructions example porcessid
then server is also call callback function app.listen(port[, callback]). Withing that function, we can access server information back from instruction and remarks.
I'm trying to accommodate myself to SignalR.
But I need a gold point to completely understand it. I feel one step away from snatch...
My codes:
Javascript:
$(function() {
var connection = $.connection.signalR;
connection.client.broadcastTotalOnline = function (totalOnlineUser) {
$('#TotalOnline').html(totalOnlineUser);
};
$.connection.hub.start().done(function() {
console.log("Connection Started!");
});
});
C#:
public class SignalR : Hub
{
public void SendTotalOnline()
{
var context = GlobalHost.ConnectionManager.GetHubContext<SignalR>();
using (var dbContextx = new db_Oyun())
{
while (true)
{
int totalOnlineUser = dbContextx.tbl_User.Count(x => x.Online);
context.Clients.All.broadcastTotalOnline(totalOnlineUser);
Thread.Sleep(1000);
}
}
}
}
Above codes are work perfect but when I call new page to inner content with AJAX.
And then I would like to use same hub, same object and same hub, different object. It not working. Not calling alert; but when I removed above signalR codes, under codes working.
$(function () {
var connection = $.connection.signalR;
connection.client.broadcastTotalOnline = function (totalOnlineUser) {
alert(totalOnlineUser);
};
});
When you start your SignalR connection, it examines the $.connection.signalR.client object to see if you added any callbacks. If you add a callback using normal assignment after the connection has started, SignalR will not pick up that callback.
To add a callback after the connection has started, you can use $.connection.signalR.client.on:
$.connection.signalR.client.on("broadcastTotalOnline", function (totalOnlineUser) {
alert(totalOnlineUser);
});
If you were trying to add a callback to a Hub you didn't already have a callback for before starting your connection, then even using .on would not work.
You must have at least one callback hooked up to every hub you plan to use before you start up your connection. The callback that you setup can be a dummy callback that is never called. Adding the callback is just you way of indicating to SignalR that your interested in messages originating from that hub.
You don't need to add any dummy callbacks in your case since you already attach to broadcastTotalOnline before starting the connection.
If you want to remove a callback, you can use $.connection.signalR.client.off with a reference to the function you previously added:
var callback = function (totalOnlineUser) {
alert(totalOnlineUser);
};
$.connection.signalR.client.on("broadcastTotalOnline", callback);
$.connection.signalR.client.off("broadcastTotalOnline", callback);
I use parse.comas backend service for my iOSapp. I was trying to do everything in objective-c since I don't have any experience with JavaScript, but turns out I will need to develop some Cloud Code Functions in JavaScript to complete my app.
A simple routine I'm trying to create:
User retrieves an object using a Cloud Function.
User saves another object in a different class.
An afterSavefunction runs in the cloud to update object first retrieved.
Now, here is my code:
var UserConfigOrientador = Parse.Object.extend("UserConfigOrientador");
var query = new Parse.Query(UserConfigOrientador);
Parse.Cloud.define('pegarOrientadorLivre', function(request, response) {
Parse.Cloud.useMasterKey();
query.greaterThan("entrevistasDisponibilidade", 0);
query.first({
success: function(results) {
response.success(results);
query = results;
},
error: function(error) {
response.error('Favor, checar rede e tentar novamente.');
}
});
});
// AfterSave
Parse.Cloud.afterSave("Agenda", function(request) {
Parse.Cloud.useMasterKey();
query.set("entrevistasDisponibilidade", 70);
query.save();
}
});
});
Now, the second function is not working, I'm getting the message that Object has no set method.
Basically, my questions are:
How can I share data between functions?
Should I keep everything in main.js or can I use another file?
I'm using webStorm for development. And the question about main.js is that after a while I will have a lot of functions and I am trying to figure out how to organize my code.
Your issue is one of scope, and poorly named variables that you're reusing for multiple purposes.
You define your query variable as a query, use it, but inside the success handler you set it to the result of the query (you now have a variable called query which is actually an instance of your UserConfigOrientador class).
When that Cloud Code finishes running, the result goes out of scope and is most likely set to undefined. You shouldn't be trying to share variables between multiple Cloud Code methods like that.
Is there something on the Agenda object that can let you know which UserConfigOrientador to update? Perhaps you could add a pointer property to the UserConfigOrientador? If you did, then you could use the following:
// AfterSave
Parse.Cloud.afterSave("Agenda", function(request) {
Parse.Cloud.useMasterKey();
var userConfigOrientadorQuery = new Parse.Query("UserConfigOrientador");
// read "userConfigOrientador" pointer property on "Agenda" object
var userConfigId = request.object.get("userConfigOrientador").id;
userConfigOrientadorQuery.get(userConfigId, {
success: function(userConfigOrientador) {
userConfigOrientador.set("entrevistasDisponibilidade", 70);
userConfigOrientador.save();
}
});
});
Mm.. I don't think it quite works the way you expect.
When your Cloud code runs, your initial var query declaration is indeed available within the scope of your cloud function and afterSave function. However, you're not passing it in correctly. As a matter of fact, I'm a little confused because your query seems to be requesting a UserConfigOrientador object while your afterSave is on an Agenda object.
So there are two different things going on here. Since you don't actually save an agenda object, I'm assuming that your response.success() returns a JSON of the UserConfigOrientador object back to client side at which point you do some manipulation then save the Agenda object based on that result.
At this point, when you save() the Agenda object now the afterSave() function will run but your query value will be the var query = new Parse.Query(UserConfigOrientador); which does not have a set method. This is why you get the error.
I'm not even sure your query = results; line will actually execute as you should be calling it at the END of your sub-routine and it signals to Parse that it is the end.
If you can tell me how you're saving the Agenda object I can probably complete the picture.
EDIT: --- abstracted but maybe this is the pattern you're looking for...
var ObjectA = Parse.Object.extend('ObjectA');
var queryObjectA = new Parse.Query('ObjectA');
Parse.Cloud.define('findObjectX', function(request, response) {
Parse.Cloud.useMasterKey();
// other query options here...
query.first({
// the first() function will return a Parse.Object
success: function(objectX) {
// Now you have objectX
// Now you want to save some other object
var otherObj = new ObjectA();
// Do things to otherObj
otherObj.save({
success: function(result) { // will be the saved otherObj
// Now you do stuff to your queried obj and save
objectX.set('something', result); // or whatever
// Note, it accomplishes what I think you want without afterSave()
}
}); // async... but we can just let this guy go
},
error: function(error) {
response.error('Favor, checar rede e tentar novamente.');
}
});
});
I have a JavaScript Websockets implementation where I would like to use a singleton model that uses one Websocket connection for multiple calls to the server but with different callback event handlers. I have the implementation working just fine but have noticed some strange behaviors with messages being directed to the wrong callback handler. Here is some code:
Connection.js file
var connection = function(){
var _socket = null;
return {
socket : function(){
if (_socket == null){
_socket = new WebSocket("ws://localhost:8081/index.ashx");
_socket.onclose = function(evt){alert('Closed');}
_socket.extraParameter = null;
}
return _socket;
},
send : function(data, callback){
var localSocket = connection.socket();
localSocket.extraParameter = new Date().toString();
localSocket.onmessage = callback;
localSocket.originalDataSent = data;
localSocket.send(data);
}
}
}();
App.js file
var App = function(){
return {
cpuUtilization : function(evt){
var localSocket = this;
var dateTimeOfRequest = localSocket.extraParameter;
var originalDataSent = localSocket.originalDataSent
var jsonData = $.parseJSON(evt.data);
if ($.parseJSON(originalDataSent).type == "cpu"){
$("#dateTimeContainer").html();
$("#cpuContainer").html(jsonData.value);
}
}
}
}();
Third Party Signal.js file
var Signal = function(){
return {
handlerProcess : function(evt){
// Does some third party stuff...
}
}
}();
usage
connection.send("{type:'process'}", Signal.handlerProcess);
connection.send("{type:'cpu'}", App.cpuUtilization);
connection.send("{type:'memory'}", Signal.handlerMemory);
connection.send("{type:'harddrive'}", Signal.handlerHardDrive);
Now where I think I am see the problem is when multiple request are made through the same websocket and the message returns. Since this is asynchronous, I have no way of tieing the request to the event callback. My solution uses the options in the handler for reference, but depending on the time it takes for the websocket request to run, the wrong callback handler is being called and process fails. I think it is failing because I am accessing properties from the websocket instance that may be changing between calls.
Is there a way to pass a reference or additional parameters along with the evt parameter? Maybe wrapping this somehow?
I think it is failing because I am accessing properties from the websocket instance that may be changing between calls.
Yes.
Since this is asynchronous, I have no way of tieing the request to the event callback.
No. You can create a closure for the callback function instead of calling using callback directly:
... send: function(data, callback){
var localSocket = connection.socket();
var extraParameter = new Date().toString();
localSocket.onmessage = function(evt) {
callback(evt.data, /* original- */ data, extraParameter);
};
localSocket.send(data);
}
But still, you have a changing onmessage callback handler. That means, an event may be sent to a handler that does not deserve it. Having an asynchronous system, you will need to add a piece of information to the server resonse that indicates which process the data belongs to. The one universal message handler then could resolve that and call the right callback.