Node.js using socket.io in multiple .js files - javascript

I want to be able to write functions in multiple .js files and use the same socket that is create in my main server.js
server.js:
var express = require('express')
var app = express()
var http = require('http')
var server = http.createServer(app)
var io = require('socket.io')(server)
var GOR = require('./gor')
var path = require('path');
app.use(express.static(path.join(__dirname, '/public')));
//handles get request and serves index.html
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/index.html');
});
//wait for server to start
server.listen(8080,()=>{
console.log("server started");
setInterval(emit_data,5000);
emit_data();
//setInterval(GOR.send_from_another_js,5000);
//GOR.send_from_another_js(io);
})
function emit_data(){
io.emit( 'update', "webserver.js");
}
As you can see from the code above, I have a function that emits to socket every 5 seconds and that works fine. I have confirmed it already.
All I want to do now, is to create a seperate.js file and keep all my functions there to make the code look cleaner. I name another .js file gor.js:
gor.js:
//I want to call this function in my webserver.js and transmit this socket
function send_from_another_js(io){
console.log("function called");
io.emit( 'update', "another_js");
}
module.exports = {
send_from_another_js
}
When I call this function in my server.js , it does not work:
server.listen(8080,()=>{
console.log("server started");
setInterval(GOR.send_from_another_js,5000);
GOR.send_from_another_js(io);
})
What is correct way to use the same .io in other .js files? The above does not work.
EDIT1
In my .html, I wait for a message on socket:
window.addEventListener('DOMContentLoaded', () => {
socket.on('update', function(number_to_set) {
console.log("socket update received");
document.getElementById('number1').innerHTML = number_to_set;
});
var button = document.getElementById("operation_code_button");
button.addEventListener("click", function(event){
var val = document.getElementById("operation_code_input").value;
console.log("socket clicked, emmiting data");
socket.emit('button_click',val);
});
})
And in my .js file I emit to this socket every 5 seconds:
server.listen(8080,()=>{
console.log("server started");
setInterval(emit_data,5000);
emit_data();
})
After 5 seconds, I can see that my webpage update data so everything works!!!
I want to declare the emit_data function inside another .js file and use it in my main .js file.
The function in my secondary .js file ( gor.js):
function send_from_another_js_1(io){
io.emit( 'update', data);
}
I want to call it in my main .js the same way I call emit_data

You need to wait for your server to get initialized. You are calling your function before socket.io is ready. That's why io.emit function is 'undefined'.
server.listen(8080,()=>{
GOR.send_from_another_js(io);
})

Edited:(3)
Trust it is what you are looking for...
"server.js"
const content = require('fs').readFileSync(__dirname + '/index.html', 'utf8');
const httpServer = require('http').createServer((req, res) => {
// serve the index.html file
res.setHeader('Content-Type', 'text/html');
res.setHeader('Content-Length', Buffer.byteLength(content));
res.end(content);
});
const io = require('socket.io')(httpServer);
const apple = require("./File2.js")
apple.send_from_another_js_1(io);
apple.send_from_another_js_2(io);
var port = 3000; //wamp server
var prompt = 'Open browser at http://localhost:'
httpServer.listen(port, () => {
console.log(prompt, port);
});
"File2.js"
function send_from_another_js_1(io){
io.on('connection', function (socket) {
socket.on('file2_1_EventTrigged', function (data) {
socket.emit('update1', "send_from_another_js_1(io) : "+ data);
console.log("+++ function send_from_another_js_1(io) called");
});
});
}
function send_from_another_js_2(io){
io.on('connection', function (socket) {
socket.on('file2_2_EventTrigged', function (data) {
socket.emit('update2', "send_from_another_js_2(io) : "+ data);
console.log("... function send_from_another_js_2(io) called");
});
});
}
module.exports = {
send_from_another_js_1,
send_from_another_js_2
}
"index.html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Content-Type" content="text/html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="keywords" content="HTML, CSS, JavaScript">
<meta name="author" content="Dr.Chaiya Tantisukarom">
<meta http-equiv="Cache-Control" content="public, max-age=31536000">
<title>NodeJS socket.io</title>
</head>
<body>
<h1 style="text-align: center;">Hello another world</h1>
<div style="text-align: center;">
<span>
<button onclick="file2_1()">file2_1</button>
</span>
<span>
<button onclick="file2_2()">file2_2</button>
</span>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('connect',()=>{
//alert('Connected');
})
function file2_1(){
socket.emit('file2_1_EventTrigged', "Hello file2_1, how are you today?");
}
socket.on('update1', (data)=>{
alert(data);
})
function file2_2(){
socket.emit('file2_2_EventTrigged', "Hi file2_2, trust you are ok.");
}
socket.on('update2', (data)=>{
alert(data);
})
</script>
</body>
</html>
Cheers !!!

When you call this:
server.listen(8080,()=>{
console.log("server started");
setInterval(GOR.send_from_another_js,5000);
GOR.send_from_another_js(io);
})
setInterval() isn't providing a parameter for GOR.send_from_another_js(), so io becomes undefined.
To fix this, I would use a second lambda expression inside of your setInterval() call.
server.listen(8080, () => {
console.log("server started");
setInterval(() => {
GOR.send_from_another_js(io);
}, 5000);
GOR.send_from_another_js(io);
});

Related

How do I link a js file to index.html in a Node.js web server?

I'm new to Node.js and I'm just trying to create simple web server that can serve HTML, JS, and CSS files.
The server works and I can view index.html in localhost. But I can't seem to link the request.js to index.html. Here's my project structure:
--public
----js
------request.js
----index.html
--app.js
app.js
const http = require("http");
const fs = require('fs').promises;
const host = 'localhost';
const port = 8000;
const requestListener = function (req, res) {
fs.readFile(__dirname + "/public/index.html")
.then(contents => {
res.setHeader("Content-Type", "text/html");
res.writeHead(200); // success status code
res.end(contents);
})
.catch(err => {
res.writeHead(500);
res.end(err);
return;
});
};
const server = http.createServer(requestListener);
server.listen(port, host, function(error) {
if (error) {
console.log('Something went wrong', error)
}
else {
console.log(`Server is running on http://${host}:${port}`);
}
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="/js/request.js" defer></script>
<title>Water Web Dev</title>
<body>
</body>
</html>
</head>
request.js
const axios = require('axios');
const getBtn = document.getElementById('get-btn');
const getData = () => {
axios.get('https://reqres.in/api/unknown')
.then(function (response) {
// success
console.log(response);
})
.catch(function (error) {
// error
console.log(error);
})
.then(function () {
// always executed
});
}
getBtn.addEventListener('click', getData)
You should server your css & js files as static files.

Trying to send a string message from javascript server to client using sockets; when pressing HTML button

I am new to this area so forgive me if I fail to explain my question well.
I am essentially trying to send a string "Hello, I connected to the port" to my Javascript client, only when I have pressed a HTML button.
FOR TESTING PURPOSES:
I have been successful in running a client and server Javascript socket connection, and can receive data back and forth. However when trying to link this to my html page I fail to connect them and send data.
CLIENT.JS:
const net = require('net');
const client = net.createConnection({ port: 9898 }, () => {
console.log('CLIENT: I connected');
client.write('CLIENT: Hello this is client!');
});
client.on('data', (data) => {
console.log(data.toString());
client.end();
});
client.on('end', () => {
console.log('CLIENT: I disconnected from the server.');
});
SERVER.JS
const net = require('net');
const server = net.createServer((socket) => {
socket.on('data', (data) => {
console.log(data.toString());
});
socket.write('SERVER: Hello! \n');
socket.end('SERVER: Closing connection now \n');
}).on('error', (err) => {
console.error(err);
});
server.listen(9898, () => {
console.log('opened server on', server.address().port);
});
if you save the above code and run them using the lines:
node server.js
node client.js
You will find that they send messages between them quite nicely.
The issue starts when I try to run my html page (which is served using node.JS on port 8083)
(I server my HTML page using npx http-server --cors)
An approach I tried was to place the code in client.js into a function and then call it in my html button:
<input type = "button" onclick = "outputData()" value = "Display">
(outputData being the function that contains the code in client server)
I'm not sure if its even something that can be done, but I'd like to essentially start my server.js from my HTML page, when a button is clicked, so that it can begin sending the data. I'd want to run "node client.js" on terminal and see that messages are coming through as server.js would have been started from my webpage
Any advice would be highly appreciated. Thank you for taking the time.
Information about socket.io library, https://socket.io/docs/v3/client-api/index.html
Sending message index.html
<html>
<body>
<input type="button" onclick="javascript:sendMessage()" value="Click here"/>
<script>
const sendMessage = () => {
var new_message = {message: "this is my message"}
socket.emit('new_message', new_message);
}
</script>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io("http://localhost:8080");
</script>
</body>
</html>
server.js
socket.on('new_message', (data) => {
var New_Details = {
message: data.message
};
socket.broadcast.emit('update_message', New_Details);
console.log(data.username + ' just wrote ' + data.message);
});
I managed to solve this by using Websockets. Where my webserver acted as the client, and I adjusted my server.js to the following:
SERVER.JS
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 9898 });
wss.on("connection", ws => {
console.log("New client connected!");
ws.on("message", data => {
console.log(`Client has sent us: ${data}`);
ws.send(data.toUpperCase());
});
ws.on("close", () => {
console.log("Client has disconnected!");
});
});
HTML
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/dcode.css">
<link rel="shortcut icon" href="/assets/favicon.ico" type="image/x-icon">
<title>WebSockets</title>
</head>
<body>
<script>
const ws = new WebSocket("ws://localhost:9898");
ws.addEventListener("open", () => {
console.log("We are connected!");
ws.send("Hey, how's it going?");
});
ws.addEventListener("message", ({ data }) => {
console.log(data);
});
</script>
</body>
</html>

nodejs, socket, https - Socket makes no connection but only disconnects

I've been through A LOT of issues in here about this topic but so far no answers has been the solution for my problem.
My setup is an AWS EC2 server with apache installed. I've installed node.js in the /node folder containing a server-file called server.js and in the root folder I have my client-file index.php. I have Let´s Encrypt SSL-certificates for my domain and therefore I need everything to run over https. I have opened up the port 3000 for all traffic en AWS.
Server.js
const app = require('express')();
const fs = require('fs');
const options = {
key: fs.readFileSync("/etc/letsencrypt/live/example.com/privkey.pem"),
cert: fs.readFileSync("/etc/letsencrypt/live/example.com/fullchain.pem")
};
const http = require('https').Server(options, app);
const io = require('socket.io')(http);
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
});
});
http.listen(3000, function(){
console.log('listening on 3000');
});
index.php
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket Test</title>
</head>
<body>
<ul id="events"></ul>
<script src="https://cdn.jsdelivr.net/npm/socket.io-client#2/dist/socket.io.js"></script>
<script>
const events = document.getElementById('events');
const newItem = (content) => {
const item = document.createElement('li');
item.innerText = content;
return item;
};
const socket = io('https://example.com:3000', {transports: ['websocket', 'polling']});
console.log(socket);
socket.on('connect', () => {
console.log("did connect");
events.appendChild(newItem('connect'));
});
socket.on('disconnect', () => {
console.log("did disconnect");
});
</script>
</body>
</html>
The problem
When I start my node server everything seems right. Executing node server.js returns listening on 3000 as supposed. When I go to index.php it never returns did connect BUT when I then exit the server node I get the did disconnect message in the browser console.
Also the server never returns anything else but listening on 3000.
Please help me :-)
Since the recent update to v3.0.0, version 2.x.x clients are not compatible so won't be able to connect.
The fix is to make sure both client and server are using the same versions, or use the server served version /socket.io/socket.io.js (which is not always possible, webpack etc)
Related issue on github: https://github.com/socketio/socket.io-client/issues/1390

Load data to Snowflake using NodeJS/Express

I have a simple HTML with single button. JavaScript (being client-side script) captures time of each click. I got stuck on how to pass event/time occurence of a click and display using Node.js to later transfer it intoo Snowflake database.
From what I reviewed it seems that workaround is JSDOM however currently it throws me an error.
Here are the topics I reviewed:
https://stackoverflow.com/questions/13840429/what-is-the-difference-between-client-side-and-server-side-programming
https://stackoverflow.com/questions/38748996/using-document-object-in-nodejs
[UPDATE - November 2020]
After reviewing below I came up with new code splitting the project into 3 files. Still need help with inserting data into Snowflake, not sure how to bind click event to the sql text. Overall goal is to insert datetime of click event into Snowflake's table:
https://gist.github.com/aerrity/fd393e5511106420fba0c9602cc05d35
Work in progress code:
server.js
console.log('Server-side code running');
const express = require('express');
const app = express();
// serve files from the public directory
app.use(express.static('public'));
//connect to snowflake and load data
var snowflake = require('snowflake-sdk');
var connection = snowflake.createConnection( {
account: 'xxxx',
username: 'xxxx',
password: 'xxxx'
}
);
//confirm connection is working
connection.connect(
function(err, conn) {
if (err) {
console.error('Unable to connect: ' + err.message);
}
else {
console.log('Successfully connected to Snowflake.');
// Optional: store the connection ID.
connection_ID = conn.getId();
}
}
);
// start the express web server listening on 8080
app.listen(8080, () => {
console.log('listening on 8080');
});
// serve the homepage
app.get('/', (req, res) => {
res.sendFile(__dirname + '/countClicks.html');
});
// insert data into snowflake isues, how to bind click event?
connection.execute({
sqlText: 'INSERT INTO DEMO_DB.PUBLIC.INPUT_NODEJS(CLICK_DATETIME)',
binds: [/clicked]
});
countClicks.js
const button = document.getElementById('clicks');
button.addEventListener('click', function(e) {
console.log('button was clicked');
fetch('/clicked', {method: 'POST'})
.then(function(response) {
if(response.ok) {
console.log('Click was recorded');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
});
countClicks.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Node + Express + Snowflake example</title>
</head>
<body>
<h1>Node + Express + Snowflake example</h1>
<p id="counter">Loading button click data.</p>
<button id="myButton">Click me!</button>
</body>
<script src="countClicks.js"></script>
</html>

Socket.io > Simple server to client message

my problem between socket.io and HTML5
Javascript Server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function (req, res) {
res.sendfile('index.html');
});
io.on('connection', function (socket) {
socket.emit('news', 'Hello');
});
http.listen(3000, function () {
console.log('listening on *:3000');
});
HTML5:
<html>
<head>
<meta charset="UTF-8">
<title>My Title</title>
</head>
<body>
<input type="button" id="getButton" value="Get Rooms">
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$("#getButton").click(function () {
socket.on('news', function (data) {
alert(data);
});
});
</script>
</body>
</html>
When I click on the button (ID: getButton) I don't get an alert. The server ist working and I can access the page without any problems.
I am currently a newbie in socket.io/javascript (installed yesterday), if you have good informative pages about socket.io please post the link under this topic, thanks.
best regards
You're emitting the news message as soon as you connect, so it has already fired by the time you click your button. Try changing your code to this and you should see your alert:
var socket = io();
socket.on('news', function(data) {
alert(data);
});
You could trigger the event on a button with something like this:
Server:
io.on('connection', function(socket) {
//socket.emit('news','Hello');
});
// Return the news when it's requested
io.on('giveMeNews', function(socket) {
socket.emit('news', 'Here is your news');
});
Client:
// Listen for the news message
socket.on('news', function(data) {
alert(data);
});
// Request news from the server
$("#getButton").click(function() {
socket.emit('giveMeNews');
)};

Categories

Resources