socket.io emit in loop until client responds? - node.js

I would like to emit a message to the client every X seconds until the client clicks a button and acknowledges receipt.
Any ideas on how I might accomplish this? New to Node but I am hoping I can get this done with Node and Sockets.io.
Thanks in advance for any insight or help to get me in the right direction.

I think the best way to accomplish this would be to create a new class that extends the "vanilla" Node.js event class. You will need to require it first like so:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
https://nodejs.org/api/events.html
Once you've got your class, what you will need to do is creating a child process, to do so, you can refer to the official documentation here:
https://nodejs.org/api/child_process.html
Inside this process you can create your loop and send a message through the socket. The goal of extending the events class is to be able to create an Inside event emission which you can listen to detect specific events (like socket closed, or anything you'd like to track)
I hope this answers your question.

This is a simple setup just to give you an idea of how to do it:
node server (very basic, only socket.io, nothing else):
const io = require('socket.io')(3000);
const interval = 1000;
io.on('connection', function (socket) {
console.log(socket.id + ' has connected');
var foo = setInterval (function () {
socket.emit('foo');
}, interval);
socket.on('confirmed', function () {
console.log('confirmation received from ' + socket.id);
clearInterval(foo);
});
});
console.log('socket.io server started at port 3000');
index.html (open it in your browser and see what happens):
<!doctype html>
<html>
<head>
<title>Testing socket.io</title>
</head>
<body>
<button id="button">Confirm</button>
<p id="socket">waiting...</p>
<p id="alert">foos counter: </p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script>
<script>
var socket = io("http://localhost:3000");
var counter;
socket.on('connect', function() {
counter = 0;
document.getElementById("socket").innerHTML = "connected";
document.getElementById("button").addEventListener("click", function () {
socket.emit("confirmed");
});
});
socket.on('foo', function() {
counter++;
document.getElementById("alert").innerHTML = "foos counter: " + counter;
});
</script>
</body>
</html>

Related

Enter twice in socket.on event

I'm new to Angular and Node.js.
My code executes a socket.emit to a server side function and receives a response in the socket.on event ('listartists').
Unfortunately, he enters twice in this event and I do not understand why.
On the server side (app.js) I put logs and the function is called correctly once, but then it goes through the socket.on twice ('listartists').
Thank you all
var appAng = angular.module('appAng', []).controller('myCtrl', function($scope) {
socket.on('listartists', function(msg) {
// !!! enter twice this part of the code
var ClientMessage = JSON.parse(msg);
if (ClientMessage.ClientID == GetClientUniqueId()) {
var artistslist = JSON.parse(ClientMessage.Message);
$scope.$apply(function() {
var artistslist=JSON.parse(ClientMessage.Message);
$scope.artists = artistslist;
});
}
});
});
i modified my code as :
socket.on('listartists', function(msg){
var ClientMessage=JSON.parse(msg);
if (ClientMessage.ClientID== GetClientUniqueId())
{
console.log("Arriva Lista Artisti " + ClientMessage.ClientID);
var artistslist =JSON.parse(ClientMessage.Message);
$scope.artists = artistslist;
$scope.$apply( function(){});
}
});
Anyway if i remove $scope.$apply( function(){}); the socket.on event is called only once,
otherwise it passes twice from there.
I think the problem is the management of the SCOPE some idea?

SocketIO dont fire first client events

I am building a chat app. The issue is that, socket.io does not emitthe keypress event on the first client, when fired.
I built this with Ionic 3 & Angular 5
Here's the "bug"
My view.html
<p *ngIf="typing == true">... is typing</p>
<ion-item no-lines>
<ion-input
type="text"
placeholder="Message"
[(ngModel)]="message"
(keypress)="userIsTyping()">
</ion-input>
</ion-item>
My view.ts
userIsTyping() {
this.socket.emit('typing');
this.socket.on("updateTyping", (data) => {
console.log('typingInSocket = ' + data.isTyping);
this.typing = data.isTyping;
});
console.log('typing = ' + this.typing);
My server.js
io.on('connection', (socket) => {
socket.on('typing', () => {
socket.broadcast.emit('updateTyping', {
isTyping: true
});
setTimeout(() => {
socket.broadcast.emit('updateTyping', {
isTyping: false
});
}, 2000);
});
Do you have any solution ?
Thanks you guys !
Okay, so the issue is how you're going about defining your socket listener. You're setting the event listener for this.socket.on("updateTyping") inside the block of code that only runs once you start typing. So every time you start typing, you create a new duplicate event listener. However, because it's only defined when you start typing, the "is typing..." won't show up until you've typed at least one character, at which point it'll start listening.
The answer is basically to move that socket listener outside of the userIsTyping() function.
this.socket.on("updateTyping", (data) => {
console.log('typingInSocket = ' + data.isTyping);
this.typing = data.isTyping;
});
userIsTyping() {
this.socket.emit('typing');
}

Testing Node.js server and Flash socket

I'm trying to establish socket connexion between a Node.js server and a Flash (Flex) application. I have some unexpected results that I can't explain by myself.
Here are my code.
Flex :
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="windowedapplication1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import com.pnwrain.flashsocket.FlashSocket;
import com.worlize.websocket.WebSocket;
import mx.events.FlexEvent;
private var _flashSocket:FlashSocket;
private var _webSocket:WebSocket;
private var _xmlSocket:XMLSocket;
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
_xmlSocket = new XMLSocket();
_xmlSocket.addEventListener(Event.CLOSE, function():void{trace('close')});
_xmlSocket.addEventListener(DataEvent.DATA, onData);
_xmlSocket.addEventListener(Event.CONNECT, function():void{trace('connect');});
_xmlSocket.addEventListener(IOErrorEvent.IO_ERROR, function():void{trace('io error')});
_xmlSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function():void{trace('sec error')});
_xmlSocket.connect("127.0.0.1", 8888);
}
protected function button1_clickHandler(event:MouseEvent):void
{
_xmlSocket.send("client test");
}
protected function onData(event:DataEvent):void
{
trace(event.data);
}
]]>
</fx:Script>
<s:VGroup>
<s:TextInput id="ti" />
<s:Button label="test" click="button1_clickHandler(event)" />
</s:VGroup>
</s:WindowedApplication>
My simple Node.js server :
const net = require('net');
var server = net.createServer(function(socket)
{
socket.on("data", function(message){
socket.write(message + "\n");
});
socket.on("connect", function(){ // Never triggered
console.log("connected to client\n");
});
socket.on("drain", function(){ // Never triggered
console.log("drain !\n");
});
socket.on("close", function(){
socket = undefined;
});
setInterval(function(){
if(socket)
{
socket.write("test\n");
}
}, 5000);
}).listen(8888, "127.0.0.1");
So when I click on my Flex button, data is sending from my app to my server and from my server to my app so it seems to be good.
When I waiting for 5 seconds my Flex does not receive "test" String as expected but when I click on my app button after 1 minute or less I receive data like this :
test
test
test
test
.....
client test
It seems that my server doing some "retention of information" but I can explain why or why some events are never triggered as it should be (?).
Thanks for help
Ok I'm just finding solution after posting (it's always the case no ?)
I have to use \0 in message.
socket.write("test\0");
NOT
socket.write("test\n");

Possible scoping issue

A possible node.js/backbone.js/socket.io scoping issue I can't wrap my head around.
(snippet from) server.js
var app = express();
var server = http.createServer(app);
io = io.listen(server);
(snippet from) index.html
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect(window.location.origin);
</script>
(snippet from) js/views/map.js
(function() { // self invoking anonymous function so we are able to
// create the private variable "map" that can be shared here
var map;
var webSocket = window.socket;
window.MapView = Backbone.View.extend({
initialize: function() {
this.render();
webSocket.on("marker dropped", this.propNewMarker);
},
events: {
"click .dropmarker" : "dropMarker"
},
dropMarker: function(event) {
console.log("This fires!!!");
webSocket.emit('marker dropped', { my: 'data' });
},
propNewMarker: function() {
console.log("someone dropped a marker (im in map.js)");
},
(snippet from) MapView.html
Drop marker
Behavior I am going for
Clicking on the "dropmarker" button in MapView.html should instigate the webSocket.emit action in dropMarker. (it fires off the console.log without any problems)
Tested
When I add
io.sockets.emit('marker dropped', { 'message': 'ello wurldz' });
into server.js, the propNewMarker function in map.js is fired correctly.
Preliminary conclusion
It seems that I am struggling with a scoping issue at the level of the buttonclick.
I'm not able to fire a websocket event there.
Any thoughts ? or should I offer more insights in the code before this can be debugged? (tried to keep it as clean as possible)
This doesn't look like an issue with the scope but in fact how you are using the socket
In order for propNewMarker to be called the server must emit a message on marker dropped
On the server if you add
io.sockets.on('connection', function (socket) {
socket.on('marker dropped',function(msg){
socket.emit('marker dropped',msg);
});
});
Then the client should respond just fine to the event. I did some testing and it looks like your scoping is just fine.

Socket IO times out after some time of innactivity, doesn't work, why?

I am new to socket IO and all, I've been working with it for about the last month, but I have noticed over the time that if I let my website sit and not do anything for a small amount of time, (Im not sure how much), but it seems to timeout, and the events aren't called unless I reload the page. There must be a way to fix this?
my server code:
var io = require('socket.io').listen(4000);
var users = {};
io.disable('heartbeats');
////////////////USER CONNECTED
io.sockets.on('connection', function (socket) {
socket.emit('connected');
socket.on('session', function (session) {
///all my other functions here
});
});
then included on my page is:
<script>var socket = io.connect("http://<?php print $_SERVER["SERVER_NAME"]?>",
{port: 4000, 'reconnect': true,'reconnection delay': 1500});</script>
<script type="text/javascript" src="js/ws/data/data.js"></script>
data.js is where all of my socket io functions are for the user end.
Try removing this line:
io.disable('heartbeats');
See Configuring Socket.IO.

Resources