Cannot send message to client in nodejs with socket.io - javascript

I have 2 pages: play page, live page and server. I want to use socket.io to do this: i want to send data from play page to server and then to live and show a text that update automatically when I change it in play page.
play page emit this
var n = <%-JSON.stringify(v1)%>;
var socket = io.connect('http://localhost:3000');
socket.emit('event', { message: n });
server code
var server = app.listen(3000); //port 3000 is only for sockets. my app has web traffic on port 5000.
var io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.on('event', function(data) {
console.log('A client sent us this dumb message:', data.message);
var n = data.message;
console.log("");
console.log("data received from play client..trying to send to live");
console.log("");
console.log("var n is");
console.log(n);
console.log("sending data...");
socket.emit('event', { message: n });
Whatever I do in live page it don't receive message.
I solved 50% of my problem creating another socket in server.js that listen to port 3002 and this worked. But now my content don't update automatically on live page. I have to refresh manually and I don't want this.
This is my new server.js code that worked(without realtime update on live.ejs page):
const express = require('express');
const store = require('./store');
const storeLyric = require('./storeLyric');
const searchF = require('./search');
// middleware to handle HTTP POST request
// extract the entire body portion of an incoming request and exposes it on req.body
const bodyParser = require('body-parser');
const app = express();
app.set('port', (process.env.PORT || 5000));
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
///new
var server = app.listen(3000);
var io = require('socket.io')(server);
var server2 = app.listen(3002);
var io2 = require('socket.io')(server2);
io.on('connection', function(socket) {
socket.on('event', function(data) {
console.log('A client sent us this dumb message:', data.message);
var n = data.message;
console.log("");
console.log("data received from play client..trying to send to live");
console.log("");
console.log("var n is");
console.log(n);
console.log("sending data...");
io2.on('connection', function(socket2) {
socket2.on('live', function(data2) {
console.log('status from live client:', data2);
socket2.emit('live', n);
});
});
////////////////////
});
});
//end new
////////////
// default page
app.get('/', (req,res) => {
let students = [];
var end = req.query.end;
if(end==1 || end==2){
io2.on('connection', function(socket2) {
socket2.on('live', function(data2) {
console.log('status from live client:', data2);
socket2.emit('live', '');
});
});
}
store.studentList().then((req,respond) => {
students = req;
res.render('pages/index', {
title: '',
students:students
})
})
})
//live page
app.get('/live', function (req, res) {
res.render('pages/live', {
n:'gsgs'
})
})
// search page
app.get('/search', (req,res) => {
let search = [];
var q = req.query.q; // $_GET["q"]
searchF.search(q).then((req,respond) => {
search = req;
res.render('pages/search', {
search:search,
q:q
})
})
})
// play page
app.get('/play', (req,res) => {
let lyrics = [];
var vers = req.query.vers; // $_GET["vers"]
var for_id = req.query.for_id; // $_GET["vers"]
storeLyric.lyrics(for_id, vers).then((req,respond) => {
lyrics = req;
res.render('pages/play', {
title: '',
lyrics:lyrics
})
});
////////
})
app.listen(app.get('port'), () => {
console.log("Listening to port: ", app.get("port"))
});
What I'm doing wrong and why socket.io doesn't work in realtime?
Thanks for help!

You need to emit the event from server side to the client side and then catch data there
var server = app.listen(3000);
var io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.on('event', function(data) {
var n = data.message;
io.sockets.emit('event', message);
});
And then on frontend in live page you write this
var n = <%-JSON.stringify(v1)%>;
var socket = io.connect('http://localhost:3000');
socket.on('event', (data)=>{
console.log(data)
});

Related

Node spits out this random error, I cant see the problem in my code

I am working on a esp32 wifi speaker, I got the board going, and now I need to make a server from where you can stream what songs you'd like. I'm new to working on the backend and i'm having trouble with this error: node:internal/errors:465 ErrorCaptureStackTrace(err);
Here is my code:
const fs = require("fs");
const ytdl = require("ytdl-core");
const express = require("express");
var cors = require("cors");
var path = require("path");
const app = express();
var http = require("http").createServer(app);
const io = require("socket.io")(http);
const bodyParser = require('body-parser');
const port = process.env.PORT || 8080;
const adress = '127.0.0.1';
var clientGlob = null;
var destDir = "./Music";
var songs = [];
var songDur = [];
var playing = false;
var curSong = '';
app.use(express.json()); // to support JSON-encoded bodies
app.use(express.urlencoded({ extended: true })); // to support URL-encoded bodies
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname,"index.html"));
});
app.post("/downAudio", (req, res) => {
getAudio(req.body.url, res);
});
getAudio = (videoURL, res) => {
console.log(videoURL);
var stream = ytdl(videoURL, {
quality: "highestaudio",
filter: "audioonly",
})
var videoReadableStream = ytdl(videoURL, { filter: 'audioonly'});
ytdl.getInfo(videoURL).then((info) => {
console.log("title:", info.videoDetails.title);
console.log("rating:", info.player_response.videoDetails.averageRating);
console.log("uploaded by:", info.videoDetails.author.name);
var videoName = info.videoDetails.title.replace('|','').toString('ascii');
var videoWritableStream = fs.createWriteStream(destDir + '\\' + videoName + '.mp3');
var stream = videoReadableStream.pipe(videoWritableStream);
stream.on('finish', function() {
res.writeHead(204);
res.end();
});
console.log("File downloaded and added to the queue");
songs.push(destDir + '\\' + videoName + '.mp3');
var duration = parseInt(info.videoDetails.lengthSeconds);
songDur.push(duration*1000);
console.log("Audio added to the queue")
if(!playing)
play();
});
};
play = ()=>{
playing=true;
curSong=songs[0];
setTimeout(playNext(),songDur[0]);
}
playNext = ()=>
{
fs.unlink(curSong, function (err) {
if (err) throw err;
console.log('File deleted!');
});
songs.pop()
songDur.pop();
if(songs.length!=0)
play();
else
playing=false;
}
io.on("connection", (client) => {
clientGlob = client;
console.log("User connected");
});
app.listen(port,adress, () => {
console.log(`Server started, link: ${adress}:${port}`);
});
It downloads the songs fine but it has a problem in the playnext function. I cant relate this error to anything in there. What am I doing wrong?
Also any help into improving the code and performance is welcome.
If needed I will provide more information, thanks!
Fixed the problem, for some reason it didn't like the type of function I used. After making it a normal function playnext(){}... it worked.

How can I show my connected clients to the new client in socket.io?

I am currently doing socket.io project. When I connect to new socket it shows my input username on the "usersDiv" where all clients should be there. But the thing is when I open another tab and input my name, it only has the name of the new client but when I switch to the other tab 2 client names are there. the new client doesn't show recent connected client input.
Here is my Code:
app.js(server)
const app = express();
const socket = require('socket.io');
const server = app.listen(8001, function(){
console.log('listening to port 8001')
});
const io = socket(server);
app.use(express.static('./views'));
app.set('views','./views');
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
});
io.on('connection', function(socket){
console.log('Made Connection');
socket.on('username', function(data){
let users = [];
users.push(data.userName);
io.emit('joined', users)
});
});
client.js(client)
let username = prompt('What is your username?');
let usersDiv = document.getElementById('users');
let container = document.getElementById('container');
let socket = io();
let clear = document.getElementById('clear');
let circle = document.createElement('div');
socket.emit('username', {
userName: username
})
socket.on('joined', function(data){
usersDiv.innerHTML += data + '<br>';
})
As Chris G pointed out you need to declare let users = []; outside of the event handler connection.
For an example in app.js using sockets with a express server:
const express = require('express');
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
app.use(express.static("public"));
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
});
let users = [];
io.on('connection', function(socket) {
console.log('Made Connection');
socket.on('username', function(data) {
io.emit('joined', users);
users.push(data.userName);
});
});
const listener = server.listen(process.env.PORT, () => {
console.log('app is running on port ' + listener.address().port);
});
Then for client side you can create path like: public/client.js
let username = prompt('What is your username?');
let usersDiv = document.getElementById('users');
let container = document.getElementById('container');
let clear = document.getElementById('clear');
let circle = document.createElement('div');
let socket = io.connect();
socket.emit('username', {
userName: username
});
socket.on('joined', function(data) {
usersDiv.innerHTML = data.join('<br>');
});
Also you need to be careful using html when you are appending the username or messages someone could do a xss attack.

Message dissapears after page reload

i have created a socket.io web app, when i click on the button to send a message, the message appears for a second, but when the page refreshes automatically for no reason, the message dissapears. How can i prevent the page from refreshing and how can i make socket.io save my messages.
Here is the server code:
var express = require("express");
var io = require("socket.io")(4000);
var fetch = require("node-fetch");
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
io.on("connection", (socket) => {
socket.on("message", (msg) => {
io.emit("message", msg);
});
});
app.use(bodyParser.urlencoded({ extended: true }));
var stats = [];
app.post("/api", (request, response) => {
var key = "E9BEFD12B99EF8838E61F7A74D9C6A4B";
fetch(
`http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?appid=730&key=${key}&steamid=${request.body.user}`
)
.then((res) => res.json())
.then((json) => response.send(json) | stats.push(json));
});
app.listen(3000, () => {
console.log("server running");
});
And here is the client code:
var socket = io("ws://localhost:4000/");
var send = () => {
socket.emit("message", document.getElementById("message").value);
document.getElementById("message").value = " ";
return false;
};
socket.on("message", (msg) => {
document.getElementById("messages").innerHTML = "<p>" + msg + "</p>";
});
The send function executes whenever i press a button.
To fix this, i just removed the form tags from the html file, the problem was every time when the form was submitted the page refreshed by default.

how to request the url in socket.io

I am trying get the json data from url example.com and pass that to my index.html. How can I do that. It's not working. I want to update data every 5 second file index.html.
app.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var https = require('https');
app.get('/', function(req, res) {
res.sendfile('index.html');
//How to use req object ?
});
io.on('connection', function(socket) {
console.log('A user connected');
setInterval(function() {
urlString = "https://example.com/trip?trip_id=1234";
$.get(urlString, function(data, status){
console.log('data');
})
socket.send('');
}, 4000);
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
http.listen(3000, function() {
console.log('listening on *:3000');
});
index.html
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('message', function(data){document.write(data)});
</script>
You were doing a number of things wrong:
$.get() doesn't run on the server. That's client-side jQuery code
You should create one setInterval() on your server, not a new one for each client connection
You can then just broadcast the results to all connected clients
If you document.write() in the client after the page is loaded, it just clears your original document so you want to append info to the DOM, not use document.write().
When you send data with socket.io, you send a message name and some data .emit(someMessage, someData).
Here's one way to do your code:
// server.js
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const request = require('request');
app.get('/', function(req, res) {
res.sendfile('index.html');
});
// create one and only one interval
setInterval(function() {
let urlString = "https://example.com/trip?trip_id=1234";
request(urlString, function(err, response, data) {
if (err) {
console.log("error on request", err);
} else {
console.log('data');
// send to all connected clients
io.emit('message', data);
}
});
}, 5000);
io.on('connection', function(socket) {
console.log('A user connected');
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
server.listen(3000, function() {
console.log('listening on *:3000');
});
// index.html
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('message', function(data){
let div = document.createElement("div");
div.innerHTML = data;
document.body.appendChild(div);
});
</script>

Page refresh clears all the data

I'm working on basic chat-application running on express.js and socket.io.
Server-side code:
var express = require("express");
var app = express();
var server = require('http').createServer(app);
var io = require("socket.io").listen(server);
var path = require("path");
app.use(express.static(path.join(__dirname, "public")));
app.set("view engine", "ejs");
server.listen(process.env.PORT || 3000, function() {
console.log("Server listening");
})
app.get("/", function(req, res) {
res.render("chat");
})
io.sockets.addListener("connection", function(socket) {
socket.addListener("chat-message", function(message, nickname) {
io.sockets.emit("chat-message", message, nickname)
})
})
Client-side code:
var socket = io();
var nickname = prompt("Whats your name?");
var input = document.getElementById("text-input");
var container = document.getElementById("chat-container");
input.addEventListener("keydown", function() {
if (event.keyCode == 13) {
event.preventDefault();
if (input.value !== "") {
socket.emit("chat-message", nickname + ": " + input.value);
input.value = "";
}
}
})
socket.addEventListener("chat-message", function(message) {
container.innerHTML += message + "</br>";
})
Is there any way to avoid deleting info from the webpage after refresh?
You can save all the messages and nicknames in a globar variable and send them on every new connection to the socket.
var messages = [];
io.sockets.addListener("connection", function(socket) {
//send messages to new connection
socket.addListener("chat-message", function(message, nickname) {
messages.push({message: message, nickname: nickname});
io.sockets.emit("chat-message", message, nickname)
})
})
[Edit]
Client Side
socket.addEventListener("chat-previous-messages", function(messages) {
for(let i = 0; i < messages.length; i++){
container.innerHTML += messages[i].message + "</br>";
}
})
Server side
var messages = [];
io.sockets.addListener("connection", function(socket) {
socket.emit('chat-previous-messages', messages); //new code
socket.addListener("chat-message", function(message, nickname) {
messages.push({message: message, nickname: nickname});
io.sockets.emit("chat-message", message, nickname)
})
})
Or you can serve the chat page with the messages already displayed
app.get("/", function(req, res) {
res.render("chat", messages);
})
//in the html part something like this
#chat-container
- each message in messages
message.message + '<br>'

Categories

Resources