Execute a function when a nodejs event is received - javascript

I might missing something basic, but here is my goal: I have a small instant chat example based on tutorial found here Instant Chat for drupal
The principle is to connect to a nodejs server that basically just broadcast all messages it receives.
I have this function on the client side (inside a drupal tpl.php file):
(function($) {
var myNick = 'me';
var socket = io.connect('http://<?php print $_SERVER['SERVER_ADDR'] ?>:8081');
socket.on('connect', function() {
$('#chat').addClass('connected');
});
socket.on('user message', message);
function message(from, msg) {
if (msg == 'GO') {
** EXECUTE A FUNCTION HERE **
} else { //display the message and sender
$('#lines').append($('<p>').append(from, msg));
}
}
$(document).ready(function() {
$('#send-message').submit(function() {
message(myNick, $('#messageinput').val());
socket.emit('user message', $('#messageinput').val());
clear();
$('#lines').get(0).scrollTop = 10000000;
return false;
});
function clear() {
$('#message').val('').focus();
};
});
})(jQuery);
When I send a message with content =GO, the submit is executed, the message(..,..) function is called and my specific function is executed properly.
But when I receive a GO message, the socket.on event triggers, message() function is called, but my specific function is NOT executed.
Any Idea how I can fix this?
Many thanks for your help.
Michael.

Related

Why Websocket connection is disconneting after sending message on iOS 15 devices?

I am building a website based on web socket communication. Its is working fine until iOS 14 but started breaking from iOS 15. Web socket java script client is able to open connection to server, but upon trying to send a message, the connection is getting closed. Following is my html and JS code.
function start_websocket() {
connection = new WebSocket("wss://localhost/wss/");
connection.onopen = function () {
console.log('Connection Opened');
};
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onclose = function(){
console.log("Closed");
};
connection.onmessage = function (e) {
console.log("Message Received :" + e.data);
};
}
function myFunction() {
var testText = document.getElementById("testText");
if (testText.value != "" && connection.readyState === connection.OPEN) {
connection.send("Test");
}
}
start_websocket();
myFunction() is an on-click event of a button.
A Java Websocket server is used, which will decode and send the messages based on the Data framing in https://datatracker.ietf.org/doc/html/rfc6455#section-5.
Saw different articles on the Web, but didn't found a solution to this issue. Any suggestions are much appreciated. Looking forward for your answers
Thanks in advance.

Chrome Extension: Code inside chrome.runtime.onMessage.addListener never gets executed

I'm having a lot of trouble trying to pass a variable from a content script to the popup.js using the sendMessage method.
This is the content script where I'm sending a message to the background script that contains the number of children of a DOM node:
let incomingChatsNumber = incomingChatsContainer.children().length;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
Then the background.js listen to the message and send a messag itself with the same variable to the popup.js:
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
let incomingChatsNumber = message.incomingChatsNumber;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
});
In the popup.js I have a button that will trigger some code if the "incomingChatsNumber" is more than 0 (the dom container has children):
$("#js-toggleSorting").on("click", function () {
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
if (incomingChatsNumber <= 0) {
$(".message").html("<p>No Chats To Sort, You Joker</p>");
} else {
$(".message").html("<p>Sorting Chats</p>");
//This code never gets executed
if ($("#js-toggleSorting").attr("data-click-state") == 1) {
$("#js-toggleSorting").attr("data-click-state", 0);
$("#js-toggleSorting").html("SORT INCOMING CHATS");
sortFunction(false);
} else {
$("#js-toggleSorting").attr("data-click-state", 1);
$("#js-toggleSorting").html("STOP SORTING INCOMING CHATS");
sortFunction(true);
}
save_button_state();
}
});
});
The strange thing for me is that the popup.js gets the value right I can even console.log it, but as soon as I put more code on that if conditional the code never gets executed even when the condition is ok to go.
UPDATE:
After doing the modifications suggested by ehab I realized that the variable is "undefined" all the time because of the async nature of chrome.runtime.onMessage.addListener:
Content Script:
let incomingChatsNumber = incomingChatsContainer.children().length;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
Background.js:
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
});
Popup.js (This is where I need to use the value of the incomingChatsNumber variable):
let latestIncomingChatsNumber;
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
latestIncomingChatsNumber = incomingChatsNumber;
//This Works
console.log(latestIncomingChatsNumber);
});
//This will give me an undefined value
console.log(latestIncomingChatsNumber);
I get that my problem is related to the fact that the chrome.* APIs are asynchronous so The chrome.runtime... and the console.log(...) will be executed at the same time, hence the error. So how to use the latestIncomingChatsNumber variable inside an on click event then ? Do I have to to save "latestIncomingChatsNumber" to the local storage inside the chrome.runtime.onMessage.addListener first ?
You should not put an event listener inside another event handler, this is an extremely bad practice even if it do what you think it should be doing, this will cause memory leaks for you down the road, and makes the code hard to read and semantically incorrect.
It seems based on looking at your code the problem is that the handler for the message gets called multiple times because of previous event listeners added in the click evet
let latestIncomingChatsNumber
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
// save this into the application state, i will use a parent scope variable you could use something else
latestIncomingChatsNumber = incomingChatsNumber
});
$("#js-toggleSorting").on("click", function () {
if (latestIncomingChatsNumber <= 0) {
$(".message").html("<p>No Chats To Sort, You Joker</p>");
} else {
$(".message").html("<p>Sorting Chats</p>");
//This code never gets executed
if ($("#js-toggleSorting").attr("data-click-state") == 1) {
$("#js-toggleSorting").attr("data-click-state", 0);
$("#js-toggleSorting").html("SORT INCOMING CHATS");
sortFunction(false);
} else {
$("#js-toggleSorting").attr("data-click-state", 1);
$("#js-toggleSorting").html("STOP SORTING INCOMING CHATS");
sortFunction(true);
}
save_button_state(); // i believe this function saves the attributes to the dom elements
}
});
if save_button_state does a good job the code i shared should work

setInterval running more times than intended?

I have an application written in node.js using socket.io. The main event loop looks like this:
io.on("connect", function(CLIENT) {
//Run this code when a client connects
SERVER.connectPlayer(CLIENT);
//Recieve input from client
SERVER.handleInput(CLIENT);
//Run this code when a client disconnects
CLIENT.on("disconnect", function() {
SERVER.disconnectPlayer(CLIENT);
});
});
function main() {
SERVER.update();
}
setInterval(main, SERVER.tickRate);
This works fine, but I'm having an issue with SERVER.handleInput:
//Recieve input from the client
Server.prototype.handleInput = function(client) {
client.on("sendKey", function(data) {
client.player.handleKey(data.key, data.pressed);
});
client.on("sendMouse", function(data) {
client.player.mouse_x = data.x;
client.player.mouse_y = data.y;
});
}
Both of these work fine, but the second method client.on("sendMouse") triggers my main() loop above whenever it is run. I've tried commenting out the body of sendMouse but that doesn't change anything.
This method is being triggered by the client whenever the user moves the mouse. This is the code I'm using:
//Handles input on the client and sends it to the server
Game.prototype.bindKeys = function() {
var game = this;
this.input = {};
document.addEventListener("mousemove", function(event) {
game.mouseMove(event);
}, false);
}
Game.prototype.mouseMove = function(event) {
this.setMousePos(event);
client.emit("sendMouse", this.mouse);
}
setMousePos just figures out the current position of the cursor and sets it so that the client knows what coordinates to send back to the server. If I remove sendMouse on the client the game runs perfectly but otherwise my main setInterval loop is being run additionally every time sendMouse triggers.
I have no idea what would cause this. The keyboard input works perfectly fine. I'd greatly appreciate any advice.

socket.on() not receiving data

I am having a problem with getting socket.on to work
$('#showmsg').click(function() {
var socket = io.connect('http://localhost:3000');
var msgText = $('#msgtext');
socket.emit('show msg', msgText.val());
});
That code works, as shown by using
io.sockets.on('connection', function(socket) {
socket.on('show msg', function(data) {
console.log(data);
});
});
in server.js, my main app file, however in another file, when I use the code
$(document).ready(function (){
var socket = io.connect();
socket.on('show msg', function(data) {
$('#container').hide();
});
});
Nothing happens. Does anyone know how I can get this code to work?
When you connect in the client, you have to wait for the connect message before you can send data with .emit(). As you have it now, you are trying to send the data before the connection has finished so the data is lost.
See the client-side example here: http://socket.io/docs/#sending-and-getting-data-(acknowledgements)
I think what's happening is that in your document.ready function, you are trying to call io.connect() but you are then calling the show message before your socket has connected. Try doing it like this
socket.on('connect', function (){
socket.on('show msg', function(data) {
$('#container').hide();
});
});
Nothing happens because you don't emit anything.
$(document).ready(function (){
var socket = io.connect('http://localhost:3000');
socket.on('show msg', function(data) {
$('#container').hide();
});
socket.emit('show msg', 'right now I am emitting data');
});

Reconnect hub necessary

I have simple project in ASP.NET Web site with signalr.
Code for start connection hub:
var scriptStarted = 'var myHub = $.connection.' + hubName + ';' + methodNameInitHub + '(myHub);';
$.connection.hub.error(function () {
alert("An error occured");
});
$.connection.hub.start()
.done(function () {
eval(scriptStarted);
myHub.server.registerClient($.connection.hub.id, clientIdentifier);
})
.fail(function () { alert("Could not Connect!"); });
This method is call in "methodNameInitHub + '(myHub);"
function methodInitEventHub(hub) {
if (hub) {
hub.client.addEvent = function (eventOperationName, eventType) {
$("#events").append("<li>" + eventOperationName + ", " + eventType + "</li>");
};
}
}
Code for stop connection hub:
$.connection.hub.stop();
When I load .aspx page and start hub all code execute without errors, but event from server not recieved.
After I stop and start again hub connection events begining received in client (browser)
http://clip2net.com/s/2CP2e
Why I need to restart connection hub for begin received event from server ?
Thanks.
The reason you're having issues is because you must have at least 1 client side hub function prior to calling start otherwise you will not be subscribed to the hub.
Try doing
myHub.client.foo = function() {}
prior to start.
The reason why it works after you stop then re-start the connection is because your script binds a new client method, hence allowing you to subscribe to the hub after you've restarted the connection.
Hope this helps!

Categories