I am working on a node project using socket.io but when a message is emitted it goes to the sender only and not to other connected clients. please what could I be doing wrong?
this my socket server and client code below.
node - index.js
...
io.on("connection", (socket) => {
//When a new user join
socket.on("joined", (data) => {
socket.emit("welcome", "Welcome to test");
});
//on send
socket.on("send_message", (data) => {
const {name, message} = data;
socket.emit("recieve_message", {name, message});
});
});
...
client - socket.html
...
<body>
<form action="">
<input id="name" autocomplete="off" />
<input id="message" autocomplete="off" /><button>Send</button>
</form>
<ul id="messages"></ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.0/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script>
var socket = io.connect('http://localhost:3005');
$('form').submit(function () {
socket.emit('send_message', {name: $('#name').val(), message: $('#message').val()});
$('#message').val('');
return false;
});
socket.emit('joined');
socket.on('welcome', function (msg) {
$('#messages').append($('<li>').text(msg));
});
socket.on('recieve_message', function (msg) {
$('#messages').append($('<li>').text(`${msg.name} - ${msg.message}`));
});
</script>
</body>
...
To send to everyone in the channel use
socket.broadcast.emit()
this will broadcast the message.
Use this cheatsheet for reference next time.
https://socket.io/docs/emit-cheatsheet/
Related
I'm working on an application using nodejs, mysql and express currently and I have run into an issue with fetching data from my database.
I have a POST form in the client side for booking and I want to implement a feature for the client to only be able to see non-booked times for the date which they have selected. But the problem is that once they select a date the request gets stuck in pending.
ps. this is a school project so i'm very new to nodejs and programming any help would be greatly appreciated
Heres my router.js file:
const express = require('express');
const router = express.Router();
const pool = require('../config/database.js')
router.get('/', (req, res) => {
res.render('home.ejs');
});
router.get('/book', function(req, res){
res.render('book.ejs')
});
router.get('/book/:date', function(req, res) {
const date = req.params.date;
console.log('Start of route handler');
// Fetch all bookings for the given date
pool.query('SELECT time FROM bookings WHERE date = ?', [date], function(err, bookings) {
if (err) {
console.error(err);
return res.status(500).send({ error: 'Something went wrong on the server' });
}
console.log('SQL query success');
// Get all available times for the given date
try {
const availableTimes = getAvailableTimes(date, bookings);
console.log('Successfully retrieved available times');
res.json(availableTimes);
} catch (error) {
console.error(error);
res.status(500).send({ error: 'Something went wrong on the server' });
}
});
});
// Function to get all available times for a given date
function getAvailableTimes(date, bookings) {
const allTimes = ['09:00:00', '10:00:00', '11:00:00', '12:00:00', '13:00:00', '14:00:00', '15:00:00', '16:00:00', '17:00:00', '18:00:00'];
const bookedTimes = bookings.map(function(booking) {
return booking.time;
});
const availableTimes = allTimes.filter(function(time) {
return !bookedTimes.includes(time);
});
return availableTimes;
}
module.exports = router;
client-side file:
<!DOCTYPE html>
<html lang="en">
<%- include("./partial/head.ejs"); -%>
<body>
<%- include("./partial/header.ejs"); -%>
<h1 id="bookHeader">Book an Appointment</h1>
<form method="post" action="/Bokning" class="bookForm">
<div class="bookFirstForm">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required />
<label for="email">Email:</label>
<input type="email" id="email" name="email" required />
<label for="phone">Phone:</label>
<input type="text" id="phone" name="phone" required />
</div>
<div class="bookSecondForm">
<label for="tjänst">Tjänst:</label>
<select name="tjänst" id="tjänst">
<option value="Klippning">Klippning</option>
<option value="Skägg">Skägg</option>
<option value="Behandling">Behandling</option>
</select>
<label for="barber">barber:</label>
<select name="barber" id="barber">
<option value="Mushtaq">Mushtaq</option>
<option value="Viggo">Viggo</option>
<option value="Kacper">Kacper</option>
</select>
</div>
<div class="bookThirdForm">
<label for="date">Datum:</label>
<input type="date" id="date" name="date" required />
<label for="time">Tid:</label>
<select id="time" name="time">
</select>
</div>
<button type="submit">Boka Nu!</button>
</form>
<%- include("./partial/footer.ejs"); -%>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
const dateInput = document.getElementById('date');
const timeInput = document.getElementById('time');
// Listen for changes to the date input
dateInput.addEventListener('change', function() {
// Get the selected date
const selectedDate = this.value;
// Make an API call to the server to fetch the booked times for the selected date
fetch(`/book/${selectedDate}`)
.then(response => response.json())
.then(availableTimes => {
// Clear the time input
timeInput.innerHTML = '';
// Populate the time input with the available times
availableTimes.forEach(function(time) {
const option = document.createElement('option');
option.value = time;
option.textContent = time;
timeInput.appendChild(option);
});
})
.catch(error => console.error(error));
});
</script>
</body>
</html>
I have tried putting console logs in my code but I get nothing in response
I think you miss the async and await in your code
router.get('/book/:date', async function(req, res) { // MAKE async CALLBACK
const date = req.params.date;
console.log('Start of route handler');
// Fetch all bookings for the given date
pool.query('SELECT time FROM bookings WHERE date = ?', [date], async function(err, bookings) { // MAKE async CALLBACK
if (err) {
console.error(err);
return res.status(500).send({ error: 'Something went wrong on the server' });
}
console.log('SQL query success');
// Get all available times for the given date
try {
const availableTimes = await getAvailableTimes(date, bookings);
console.log('Successfully retrieved available times');
res.json(availableTimes);
} catch (error) {
console.error(error);
res.status(500).send({ error: 'Something went wrong on the server' });
}
});
});
// Function to get all available times for a given date
async function getAvailableTimes(date, bookings) {
const allTimes = ['09:00:00', '10:00:00', '11:00:00', '12:00:00', '13:00:00', '14:00:00', '15:00:00', '16:00:00', '17:00:00', '18:00:00'];
const bookedTimes = bookings.map(function(booking) {
return booking.time;
});
const availableTimes = allTimes.filter(function(time) {
return !bookedTimes.includes(time);
});
return availableTimes;
}
As the function is doing 2 things at one time. Firstly it is uploading data into database than it is retrieving data and displaying in fron page .All i need is I want to send response using websocket to front end that data has been uploaded successfully in db and now its going to display the data
Backend Code:
loginrouter.get('/getImages',cors(),(req,res)=>{
var array = fs.readFileSync('log.txt').toString().split("\n");
for(i in array) {
var sql = "INSERT into images (urls) values ('"+array[i]+"')";
connection.query(sql, function (err, result) {
if (!err) {
var sql = " SELECT urls FROM `images`";
connection.query(sql, function (err, result) {
if (!err) {
const wss = new WebSocketServer.Server({ port: 8081 })
wss.on("connection", (ws,r) => {
ws.send('This is a message to client');
});
res.send(result)
}
});
}
})
}
})[Here is the result snippet al i need is that when the data is fully uploaded in database a web socket should send a message that the data is uploaded successfully and now we are going to retrieve it][1]
Front end code:
<html>
<head>
</head>
<body>
<button type="button" onclick="getImage(event)" > Show Images</button><br />
<h1 style="text-align: center; color: blue">Here are the Results:</h1>
<p id="demo"></p>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.2.1/axios.js"
integrity="sha512-SXo2rCaEJmbAPoxtaSjW+/hLaVCMAJ1CX8XnIP02x6/LIaWQp4GipKxQhBwL8Tn5U/K+lD9AaM4f4mXJdKnDQw=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script>
function getImage(e) {
var exampleSocket = new WebSocket("wss://localhost:8000", "dummyProtocol");
exampleSocket.onopen = function (event) {
exampleSocket.send("WebSocket is really cool");
};
e.preventDefault();
console.log("hii");
axios
.get(
"http://localhost:8000/getImages",
{},
{
headers: { "Content-Type": "application/json" },
}
)
.then((response) => {
console.log(response.data);
for (let i = 0; i < 850; i++) {
console.log(response.data[i].urls)
document.getElementById(
"demo"
).innerHTML += `<img src="${response.data[i].urls}" style="border:1px solid black;margin-bottom:4px;margin-top:14px; margin-right: 20px" width="100px" height="100px"
alt="img">`;
}
});
}
</script>
</body>
</html>
You can't connect with ws to http server port
var exampleSocket = new WebSocket("wss://localhost:8000", "dummyProtocol");
Create an instance of ws server outside the route
loginrouter.get('/getImages'
After you uploaded your data to database, send response to the user by http that the work was done, and here you have two ways to send data by ws to user.
3.1 User gets response by http that the work was done and send a request by ws to retrieve some data.
3.2 at route getImages after sending http response, send data by ws if user already connected.
Something like this. It's not working code, only the way where you can go.
const clients = new Map();
const wss = new WebSocketServer.Server({ port: 8081 })
wss.on("connection", (ws,r) => {
ws.send('This is a message to client');
const id = uuidv4();
clients.set(id, ws);
});
loginrouter.get('/getImages',cors(),(req, res)=>{
connection.query(sql, function (err, result) {
if (!err) {
res.send(result);
clients.get(req.cookies.id).send(what_you_want_to_send)
}
});
})
I am planning for queue system application using WebSocket ,PHP ,MySQL ,HTML to send console.log from one client to another to play sound for next queue ,
now I want to check in clinet2 if console.log value which I receive it client ='Hello From Client1!' paly sound or if = 'another message' do action.
Client1
<button onclick="sendMessage()">Send Msg</button>
</body>
<script>
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:3000');
// Connection opened
socket.addEventListener('open', function (event) {
console.log('Connected to WS Server')
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
const sendMessage = () => {
socket.send('Hello From Client1!');
}
</script>
Client2
<button onclick="sendMessage()">Send Msg</button>
</body>
<script>
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:3000');
// Connection opened
socket.addEventListener('open', function (event) {
console.log('Connected to WS Server')
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
const sendMessage = () => {
socket.send('Hello From Client2!');
}
</script>
Thanks All,
I think I got some code can help me.
I add in Client 1
<script>
var connection = new WebSocket ('ws://localhost:3000');
connection.onmessage = function (event){
document.getElementById("sul").value=event.data;
};
const sendMessage = () => {
socket.send("test");
}
</script>
<output type="text" id="sul" value="" readonly></output>
and client 2
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
if (event.data =='sul 1'){
console.log('Here i can put my play sound');
playsound();
}
});
I am implementing a logic of forgot password using AWS Cognito. I am so far successful in changing the password using Prompts as given in the documentation. Here is the code
var username = document.getElementById('reset-pass').value;
var data = {
UserPoolId: _config.cognito.userPoolId,
ClientId: _config.cognito.clientId
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
// setup cognitoUser first
var cognitoUser = new AmazonCognitoIdentity.CognitoUser({
Username: username,
Pool: userPool
});
cognitoUser.forgotPassword({
onSuccess: function (result) {
console.log('call result: ' + result);
},
onFailure: function(err) {
alert(err);
},
inputVerificationCode() {
var verificationCode = prompt('Please input verification code ' ,'');
var newPassword = prompt('Enter new password ' ,'');
cognitoUser.confirmPassword(verificationCode, newPassword, this);
}
});
My question is instead of using prompts, how can I confirm the user on next page. Example On the first page a user enter the email and mail is sent using the forgotPassword(). Now user is redirected to a new page. There i wanted to enter the code as well as the new password and call the cognitoUser.confirmPassword method.
What i tried is to create a delay interval and after entering the details it would trigger clear interval on button press.
function resetPassword() {
var username = document.getElementById('reset-pass').value;
var data = {
UserPoolId: _config.cognito.userPoolId,
ClientId: _config.cognito.clientId
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
// setup cognitoUser first
var cognitoUser = new AmazonCognitoIdentity.CognitoUser({
Username: username,
Pool: userPool
});
// call forgotPassword on cognitoUser
cognitoUser.forgotPassword({
onSuccess: function (result) {
alert("Mail Sent")
},
onFailure: function (err) {
console.log(err)
},
inputVerificationCode()
{
window.myVar = setInterval(function(){
console.log('check');
}, 10000);
var verificationCode = document.getElementById('code').value;
var newPassword = document.getElementById('fpass').value;
cognitoUser.confirmPassword(verificationCode, newPassword, this);
}
});
}
The HTML Part Of the code-
<div class="change">
<form>
<label>Enter Email ID</label>
<input type="email" id="reset-pass" required />
<br />
<div class="">Next</div>
</form>
</div>
div class="change-confirm">
<form>
<label>Enter Code</label>
<input type="number" id="code" required />
<br />
<label>Enter New Password</label>
<input type="password" id="fpass" required />
<br />
<div class=""> Reset</div>
</form>
</div>
But the above code never executed. Instead it stops execution after some time.
So my question is is there any way to delay the function call of cognitoUser.confirmPassword method? I do not want to use prompts instead get the email and code in a text field after mail is sent.
A little late to the party, but it can help someone else.
You can pass the congitoUser you have created to the state, and then use cognitoUser.confirmPassword(...) by retrieving the cognitoUser object from the state.
You should consider using the aws-amplify-react which provides a withAuthenticator higher-order component that provides a login flow with forgot password, mfa, etc. And it's maintained by a team of devs who work for AWS.
https://aws-amplify.github.io/docs/js/react#add-auth
I have two client sides like
1.Agent and customer
2.In Agent .I put a google cdn of socket
3.In customer also.I put a google cdn of socket
4.In Agent Transfers the messages from to nodejs server sends to customer
5.But the customer is out the website .
I write this code in node js server side
app.io.on('connection', function(socket) {
if(arraySockets.length<2){
arraySockets.push(socket);
if(arraySockets.length==1){
SocketAgent = arraySockets[0];
}
if(arraySockets.length==2){
SocketUser = arraySockets[0];
}
}
if(arraySockets.length==2) {
console.log("dffjdsg");
console.log(socket.id);
SocketUser.on('user', function (data) {
console.log(data);
var data = {
message: 'i am from server'
}
});
SocketAgent.on('agent', function (data) {
console.log(data);
var data = {
message: 'i am from server'
}
SocketUser.emit('outputuser',data);
});
}
});
Code on Agent side
services.js file in client Agent side:
schatApp.factory('socket', function ($rootScope) {
var socket = io.connect('http://localhost:8089/');
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
});
}
};
});
controller side code in Agent side
schatApp.controller('homeController', function($scope,socket) {
socket.on('ouputuser',function(data){
alert(data);
});
$scope.Sendingmessage=function(){
var data={message:'hai simhachalam from agent'};
socket.emit('agent',data);
}
});
Client side code in customer side code
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js">
</script>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
$(document).ready(function(){
var socket = io.connect('http://localhost:8089/');
$("#sendmessage").click(function(){
var data={message:'iam from user'};
socket.emit('user',data);
});
});
</script>
</head>
<body>
<input type="button" id="sendmessage" value="submit">
</body>
</html>
I am receiving the messages from Agent to nodes server and customer to node server.
when I exchanging the messages socket object is overriding. So how can I solve the problem
socket.on('ouputuser',function(data){
alert(data);
});
data is not getting from the node js server