How do you use socket.io within electron? - node.js

I am trying to implement socket.io within an electron app. Following previous advice on a question I followed this chat app example https://socket.io/get-started/chat/ and then tried to turn it into an electron app. However it is like the functionality doesn't exist now, what am I doing wrong? The app launches but I only see the front end I can type and submit but nothing comes back. The code is as follow
main.js
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
index.js
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('chat message', (msg) => {
io.emit('chat message', msg)
});
});
index.html
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages');
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function (e) {
e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
socket.on('chat message', function (msg) {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
If I do node index.js it functions perfectly (I took the listen on port 3000 out in this question) However npm start to use as an electron app does not. Please Help!!!!!

Related

How can I create more than one message in a Socket.io chat app?

I'm building a dummy chat app to know how socket.io works (with react and node. Everything seems to work fine except that socket io emits more than one message.
It looks like for each character I type when then I press on submit it emits the message multiplying the total of characters per 2.
How can I solve this?
Thank you!
Client
import React from "react";
import { useState } from "react";
import { io } from "socket.io-client";
const App = () => {
const socket = io("http://localhost:5000");
const [input, setInput] = useState("");
const handleChange = (e) => {
setInput(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
socket.emit("chat-message", input);
};
socket.on("chat-message", (msg) => {
console.log(msg);
});
return (
<div className="App">
<h1>Chat</h1>
<form onSubmit={handleSubmit}>
<input onChange={handleChange} type="text" id="input" />
<button type="submit">Send</button>
</form>
<div id="messages">
</div>
</div>
);
};
export default App;
Server
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server, {
cors: {
origin: '*',
}
});
io.on('connection', (socket) => {
socket.on('chat-message', (msg) => {
io.emit('chat-message', msg);
})
});
server.listen(5000, () => {
console.log('listening on: 5000');
});
Because you are getting message twice from client and the server. It goes like this
you send(emit) message from client onto "chat-message"
then your client responds to socket.on("chat-message") and prints it once
your server responds to socket.on('chat-message') and emits it back to client
client react to re emitted message from server and prints again
Can you once try this code?
//client side changes
const handleSubmit = (e) => {
e.preventDefault();
socket.emit("chat-message", input);
};
socket.on("receive-message", (msg) => {
console.log(msg);
});
//server side changes
io.on('connection', (socket) => {
socket.on('chat-message', (msg) => {
io.emit('receive-message', msg);
})
});

Node.js, React socket.io emit() not working

I want to build a ReactJS/NodeJs app with Socket IO.
I am able to establish a socket connection between the client and the server, but whenever I press the button to emit a message, nothing happens on the server side, meaning the console.log('new message:', msg)is not triggered.
Client code:
import React from 'react';
import io from 'socket.io-client';
const socket = io.connect('http://localhost:4000');
function App() {
socket.on('message', msg => {
console.log('new message:', msg);
});
const handleMessageSend = () => {
socket.emit('message', 'test');
}
return (
<button onClick={handleMessageSend}>Send</button>
);
}
export default App;
Server:
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
io.on('connection', socket => {
socket.on('message', msg => {
console.log('new message:', msg);
socket.emit('message', msg)
})
})
http.listen(4000, () => {
console.log('Listening on port 4000');
})
Any ideas ? Thanks a lot in advance
I have moved socket code inside handleMessageSend.
And you can add preventDefault to prevent your page refreshing (I am not sure if you need this because you are not using a form and submit button, but you can use it for now.)
Can you please try this and let me know if it works?
React component:
import io from 'socket.io-client';
function App() {
let serverUrl = 'localhost:4000'
let socket = io(serverUrl);
const handleMessageSend = (e) => {
e.preventDefault();
socket.emit("message", "test message")
socket.on("message", function(msg){
console.log("socket working on the frontend: ", msg);
});
}
return (
<button onClick={handleMessageSend}>Send</button>
);
}
export default App;
And here server file :
const express = require ("express");
const socket = require ("socket.io");
const app = express();
const server = app.listen(4000, () => {
console.log('Listening on port 4000');
})
const io = socket(server);
io.on('connection', socket => {
socket.on('message', msg => {
console.log('socket working at the backend', msg);
io.sockets.emit('message', msg)
})
})

ace editor is not working in socket.io node app

In my Socket app, I'm trying to send programming code as a message to another client. If run the HTML only it shows the Ace editor perfectly. But when I run node app.js the ace editor doesn't work.I have downloaded ace-builds and installed npm ace-code-editor in the app, but nothing changes here is my code
app.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = process.env.PORT || 3000;
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
);
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('disconnect', function () {
console.log('user disconnected');
})
socket.on('chat message', function (msg) {
console.log("message: " + msg);
io.emit('chat message', msg);
});
});
http.listen(port, function () {
console.log('listening on *:' + port);
});
index.html
<html>
<head>
<title>Socket.IO </title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#m {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
<script src="/ace-builds/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var editor = window.ace.edit("m");
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");
$(function () {
var socket = io();
var myvar = setInterval(task, 100)
function task() {
var code=editor.getValue();
socket.emit('chat message',code);
}
socket.on('chat message', function (msg) {
editor.setValue("the new text here");
});
});
</script>
</head>
<body>
<div id="m">function foo(items) {
var x = "All this is syntax highlighted";
return x;
} </div>
</body>
</html>
Need a solution
you are calling window.ace.edit("m"); before that element becomes available.
Move script tag to the end of the file, or move ace initialization into $ call.

Append a div with an array in Node.js

I am creating a chat where there will be a div that displays the users that have connected to the server. The user's name is being taken from a prompt. I have managed to push each connected user to the array but can't figure out how to display that array. At the moment it only appends the div with the name of the individual user but I want them all to be displayed.
<body>
<div id="chatlog" class="col-sm-9">
<ul id="messages"></ul>
</div>
<div id="online" class="col-sm-3">
<div id="username"></div>
</div>
<form class="col-sm-12" action="">
<input id="type" type="text" />
<input type="submit" id="submit" />
</form>
<script>
var socket = io();
var user = prompt("What's your name?");
$('form').submit(function() {
socket.emit('chat message', $('#type').val());
$('#type').val('');
return false;
});
socket.on('chat message', function(msg) {
$('#messages').append($('<li>').text(msg));
});
socket.emit("join", user);
socket.on("join", function(user) {
$("#username").append($("<p>").text(user));
})
</script>
</body>
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var express = require("express");
var port = 3000;
var onlineUsers = [];
console.log(onlineUsers);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.on("join", function(user) {
socket.emit("join", user);
onlineUsers.push(user);
console.log(onlineUsers);
});
socket.on('chat message', function(msg) {
console.log('message: ' + msg);
io.emit('chat message', msg);
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(port, function() {
console.log('listening on *:' + port);
});
I am also open to suggestions how to do this another way but node.js is very new to me and think this might be the easiest way.
Send the array of users back to the clients when a user joins. This way all clients will have a updated user list every time a user joins. Below is a suggestion on how you could implement this
server:
socket.on("join", function(user) {
onlineUsers.push(user);
io.emit("user list", onlineUsers);
});
client:
socket.emit("join", user);
socket.on('user list', function(onlineUsers) {
$("#username").empty();
for(var i=0;i<onlineUsers.length;i++){
$("#username").append($("<p>").text(onlineUsers[i]));
}
});

How to write tests: Socket.io app unit testing

I am trying to make simple chat app using socket.io. Manually it's working fine (via browser localhost:3000/) but I want to write unit tests to verify logic of the server. I don't know which tools/libraries to use for testing.
Here is my node server code:
index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var socketCount = 0;
http.listen(3000, function(){
console.log('listening on *:3000');
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
socketCount++;
console.log('new user connected');
// Let all sockets know how many are connected
io.emit('users connected', socketCount);
socket.on('disconnect', function(){
// Decrease the socket count on a disconnect, emit
socketCount--;
io.emit('users connected', socketCount);
});
socket.on('chat message', function(msg){
// New message added, broadcast it to all sockets
io.emit('chat message', msg);
});
});
And here is my html page:
file: index.html
<html>
...
<body>
<ul id="messages"></ul>
<div class='footer'>
<div id="usersConnected"></div>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</div>
</body>
...
<script>
$(document).ready(function(){
$('#messages').val('');
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
// New message emitted, add it to our list of current messages
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
// New socket connected, display new count on page
socket.on('users connected', function(count){
$('#usersConnected').html('Users connected: ' + count);
});
});
</script>
</html>
Thanks.
I had this problem: How to do unit test with a "socket.io-client" if you don't know how long the server take to respond?.
I've solved so using mocha and chai:
var os = require('os');
var should = require("chai").should();
var socketio_client = require('socket.io-client');
var end_point = 'http://' + os.hostname() + ':8081';
var opts = {forceNew: true};
describe("async test with socket.io", function () {
this.timeout(10000);
it('Response should be an object', function (done) {
setTimeout(function () {
var socket_client = socketio_client(end_point, opts);
socket_client.emit('event', 'ABCDEF');
socket_client.on('event response', function (data) {
data.should.be.an('object');
socket_client.disconnect();
done();
});
socket_client.on('event response error', function (data) {
console.error(data);
socket_client.disconnect();
done();
});
}, 4000);
});
});

Resources