Failed to load resource: net::ERR_CONNECTION_REFUSED socket.io - node.js

I am building a simple chat application using Socket.io, Node.js, and React.js.
The server on the backend connects fine at first.
However when trying to make requests to the server from my front end the server keeps on crashing. Anyone understand why?
Here is the error..
[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
server started on port 4000
new connection
events.js:109
throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
^
TypeError [ERR_INVALID_ARG_TYPE]: The "listener" argument must be of type function. Received undefined
at checkListener (events.js:109:11)
at _addListener (events.js:344:3)
at Socket.addListener (events.js:402:10)
at Namespace.<anonymous> (/Users/macbook/Projects/chat-react/server/index.js:16:10)
at Namespace.emit (events.js:311:20)
at Namespace.emit (/Users/macbook/Projects/chat-react/server/node_modules/socket.io/lib/namespace.js:213:10)
at /Users/macbook/Projects/chat-react/server/node_modules/socket.io/lib/namespace.js:181:14
at processTicksAndRejections (internal/process/task_queues.js:79:11) {
code: 'ERR_INVALID_ARG_TYPE'
}
[nodemon] app crashed - waiting for file changes before starting...
currently my server looks like this
index.js
const express = require ('express');
const socketio = require('socket.io');
const http = require('http');
const PORT = process.env.PORT || 4000;
const router = require('./router');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
io.on('connection', (socket) => {
console.log('new connection');
socket.on('disconnect'), () => {
console.log('User has left!!');
}
});
app.use(router);
server.listen(PORT, () => console.log(`server started on port ${PORT}`));
and my client looks like this
Chat.js
import React, { useState, useEffect } from 'react';
import quertString from 'query-string';
import io from 'socket.io-client';
let socket;
const Chat = ({ location }) => {
const [name, setUserName] = useState('');
const [room, setRoomID] = useState('');
const ENDPOINT = 'localhost:4000';
useEffect(() => {
const { name, room } = quertString.parse(location.search);
socket = io(ENDPOINT);
setUserName(name);
setRoomID(room);
console.log(socket)
});
return (
<h1>Chat</h1>
)
};
export default Chat;
any help would be great.

You have an error with your code. Look here:
socket.on('disconnect'), () => {
console.log('User has left!!');
}
Notice something? Yes, the function you wanted to call is not in the parentheses. Even though that wouldn't cause a syntax error, you probably didn't want to do that. Instead, you need to put the function inside the parentheses, like so:
socket.on('disconnect', () => {
console.log('User has left!!');
});
Note: to learn more about the comma operator, refer to these sites:
https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator.
JS statement separator with commas

Related

React JS socket.io-client opens multiple connections

I have a simple React JS app connected to a socket io server. Whenever I open the app in the browser, the client sends new connection request to the server every 5 seconds.
server:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('socket id:', socket.id);
})
server.listen(3001, () => {
console.log('Listening on port 3001');
})
client:
import React from 'react';
import io from 'socket.io-client';
const socket = io('http://localhost:3001');
const App = () => {
return (
<div>Hi there!</div>
);
}
export default App;
logs on the server:
socket id: ByXQEMgeVaQ5AGw1AAAA
socket id: 8LzNQsyeYq7GSEvqAAAB
socket id: bbuYEs4kKzjxXuBsAAAC
socket id: vwprv4hnJbRlStG4AAAD
I suspect there could be something wrong on my laptop, cause I don't see anything wrong in the code, any ideas?
Thanks in advance
I would recommend calling connect inside a useEffect and return the disconnect method to be called when the component dismounts.
const [socket, setSocket] = useState(null)
useEffect(() => {
const newSocket = io('http://localhost:3001')
setSocket(newSocket)
return socket.disconnect()
}, [])
Can you try to wrap the client side socket creation in a useEffect that only runs once? I'm curious to see if the behavior still appears.
import React from 'react';
import io from 'socket.io-client';
const socket = io('http://localhost:3001');
const App = () => {
useEffect(() => {
const socket = io('http://localhost:3001');
}, [])
return (
<div>Hi there!</div>
);
}
export default App;
Actually I just found the root cause, I had a mismatch between my client version and my server version. I updated the client version to v4 and now it is working

react client: websocket.js:83 WebSocket connection to 'ws://localhost:3009/socket.io/?EIO=4&transport=websocket' failed:

i have a node backend using socket io
first in app.js initialize te app
const express = require("express")
const app = express()
module.exports = {
app,
express
}
then in io.js, i create the socket server
const { app } = require("./app");
const http = require("http");
const socketio = require("socket.io");
const server = http.createServer(app);
const io = socketio(server);
module.exports = io;
then in the server.js first i import the app.js for api calls then i import io.js
require("dotenv").config();
const { app, express } = require("./app");
const logger = require("./logger");
const io = require("./io");
then i simply add emit listen code in the server.js
io.on("connection", (socket) => {
console.log("we have a new connection");
socket.on("disconnect", () => {
console.log("the socket disconnected");
});
socket.on("join", ({ user_id }, callback) => {
// const notification = getListNotifications(user_id);
// const popup = getUserPopup(user_id);
// socket.emit("nofication", { popup: popup.count, notification });
socket.emit("nofication", { popup: 3, notificaton: { a: 1 } });
socket.join(user.room);
callback();
});
then i run the server.js file in dev mode nodemon server.js
Then in react i simply use socket.io
import io from "socket.io-client";
useEffect(() => {
socket = io("ws://localhost:3009", {
"force new connection": true,
reconnectionAttempts: "Infinity",
timeout: 10000,
transports: ["websocket"],
});
return () => {
socket.disconnect();
};
}, []);
it gives me this error in browser console
the server node.js console is receiving https protocol
i find out in other answers that it maybe some protocol issue.
happy to learn from you. Thanks in advance
Happened to me that i was listening the server with app.listen which only recieves https protocol....but i have created a seperated ws server with the server variable which should listen to a port so that the server can receive ws connection...
better to use this library npm link will make work much easier...

Socket.io v3.0.4 not connecting, v2.3 does work

Summary
I have basic sample code which works in socket.io 2.3 which does not work in socket.io 3.0, I want to understand what I need to change.
Full Description
I have a node.js / react project and I wanted to use socket.io. To do this, I implemented the example code from this article, using socket.io v3.0.4, which follows.
Server side:
const http = require("http");
const socketIo = require("socket.io");
const port = process.env.PORT || 4001;
const index = require("./routes/index");
const app = express();
app.use(index);
const server = http.createServer(app);
const io = socketIo(server);
let interval;
io.on("connection", (socket) => {
console.log("New client connected");
if (interval) {
clearInterval(interval);
}
interval = setInterval(() => getApiAndEmit(socket), 1000);
socket.on("disconnect", () => {
console.log("Client disconnected");
clearInterval(interval);
});
});
const getApiAndEmit = socket => {
const response = new Date();
// Emitting a new message. Will be consumed by the client
socket.emit("FromAPI", response);
};
server.listen(port, () => console.log(`Listening on port ${port}`));
Client Side:
import React, { useState, useEffect } from "react";
import socketIOClient from "socket.io-client";
const ENDPOINT = "http://127.0.0.1:4001";
function App() {
const [response, setResponse] = useState("");
useEffect(() => {
const socket = socketIOClient(ENDPOINT);
socket.on("FromAPI", data => {
setResponse(data);
});
}, []);
return (
<p>
It's <time dateTime={response}>{response}</time>
</p>
);
}
export default App;
on the server, I was receiving the error
socket.io:client client close with reason ping timeout
which led me to this article, which implied a version issue.
Based on that, I've attempted a few things, but specifically, I was running socket.io and socket.io-client both version 3.0.4. I uninstalled and reinstalled v 2.3.0/2.3.1. It now works flawlessly.
So my question is: what do I need to change to make this work with the more recent version of socket.io.

How to make watch() function work in mongoDB?

I am trying to build a Chat-App using Pusher for realtime communication with the help of MongoDB. These are my files.
dbMessages.js
import mongoose from 'mongoose'
const pinguSchema = mongoose.Schema({
message: String,
name: String,
timestamp: String,
received: Boolean
})
export default mongoose.model('messagecontents', pinguSchema)
server.js
import express from "express"
import mongoose from 'mongoose'
import Messages from './dbMessages.js'
import Pusher from 'pusher'
//config
const app = express()
const port = process.env.PORT || 9000
const pusher = new Pusher({
appId: "###",
key: "###",
secret: "###",
cluster: "###",
useTLS: ###
});
//middleware
app.use(express.json())
//DB config
const connection_url = "###";
mongoose.connect(connection_url,{
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true
})
const db = mongoose.connection;
db.once("open", () => {
console.log("DB connected...")
})
const msgCollection = db.collection("messagecontents");
const changeStream = msgCollection.watch();
changeStream.on("change", (change)=>{
console.log(change);
//api routes
app.get('/', (req,res) => {
res.status(200).send('hello')
})
app.get('/messages/sync', (req,res) => {
Messages.find((err, data) => {
if(err){
res.status(500).send(err)
} else{
res.status(200).send(data)
}
})
})
app.post('/messages/new', (req,res) => {
const dbMessage = req.body
Messages.create(dbMessage, (err, data) => {
if(err){
res.status(500).send(err)
} else{
res.status(201).send(data)
}
})
})
//listen
app.listen(port, () => console.log(` Server running on port: ${port}`))
What i am trying to get is the 'change' in my console, By the API http://localhost:9000/messages/new But The Error that I am getting is
[nodemon] 2.0.4 [nodemon] to restart at any time, enter rs [nodemon]
watching path(s): . [nodemon] watching extensions: js,mjs,json
[nodemon] starting node server.js C:\Users\Desktop\Pingu - Chat
App\backend\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:145
throw new Error('Collection method ' + i + ' is synchronous');
^
Error: Collection method watch is synchronous
at NativeCollection. [as watch] (C:\Users\Desktop\Pingu - Chat
App\backend\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:145:15)
at file:///C:/Users/Desktop/Pingu%20-%20Chat%20App/backend/server.js:38:36
at ModuleJob.run (internal/modules/esm/module_job.js:146:23)
at async Loader.import (internal/modules/esm/loader.js:165:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5) [nodemon] app crashed - waiting for file changes before starting...
Here is the link to the documentation docs.mongodb.com/manual/changeStreams from here what I can get is that it can be done in two ways I implemented the 'watch' way, but don't know how to implement the async-await way.
Also here is the link to the youtube video from where I was trying to learn, youtube.com/watch?v=gzdQDxzW2Tw this part start from the time-stamp 2:59:00
Can anyone Help? Thanks in Advance.
I'm sorry that the comments that you got were completely unhelpful and a waste of time. All of the code that you shared is actually helpful in terms of fixing the problem.
The issue is that you are calling the watch function without ensuring that you have a connection to the database. Connecting to mongo is async, so when you call watch function, you might still be in the process of making a a db connection. Modify your code like so...
const db = mongoose.connection;
db.once("open", () => {
console.log("DB connected...");
const msgCollection = db.collection("messagecontents");
const changeStream = msgCollection.watch();
changeStream.on("change", (change) =>
console.log(change);
);
})
I hope that helps. I am very disappointed in the other comments received.

How to integrate http2 with ExpressJS using nodejs module http2?

I am creating an api with nodejs and express and I want to integrate http2 with ExpressJS
This is my code:
'use strict';
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = process.env.PORT || 443;
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Routes variables
const indexRouter = require('./routes/index');
// Routes uses
app.use('/', indexRouter);
// Server configurations
const key = path.join(__dirname + '/security/key.pem');
const cert = path.join(__dirname + '/security/certificate.pem');
const options = {
key: fs.readFileSync(key),
cert: fs.readFileSync(cert)
}
const server = http2.createSecureServer(options, app);
server.on('error', err => console.log(err));
server.listen(port, () => {
console.log('Server running')
})
I am trying to pass express server as second parameter of createSecureServer() but I am not sure if I am right with this, cause I am getting this error:
[nodemon] 2.0.2 [nodemon] to restart at any time, enter rs [nodemon]
watching dir(s): . [nodemon] watching extensions: js,mjs,json
[nodemon] starting node index.js
_http_incoming.js:96 if (this.socket.readable)
^
TypeError: Cannot read property 'readable' of undefined
at IncomingMessage._read (_http_incoming.js:96:19)
at IncomingMessage.Readable.read (stream_readable.js:491:10)
at resume (_stream_readable.js:976:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21) [nodemon] app crashed -
waiting for file changes before starting...
It should be noted that my certificate, although self-signed and unreliable, is loading correctly.
I try not to use a third-party module if I can do it with NodeJS. Any help?
expressjs still does not officially support Node http2.
For more details visit here
But you can use node-spdy. With this module, you can create HTTP2 / SPDY servers in node.js with natural http module interface and fallback to regular https (for browsers that support neither HTTP2 nor SPDY yet):
const spdy = require('spdy')
const express = require('express')
const path = require('path')
const fs = require('fs')
const port = 3000
const app = express()
app.get('*', (req, res) => {
res
.status(200)
.json({message: 'ok'})
})
const options = {
key: fs.readFileSync(__dirname + '/server.key'),
cert: fs.readFileSync(__dirname + '/server.crt')
}
console.log(options)
spdy
.createServer(options, app)
.listen(port, (error) => {
if (error) {
console.error(error)
return process.exit(1)
} else {
console.log('Listening on port: ' + port + '.')
}
})
For more datils on spdy, visit here.
If you have an option for other frameworks you can use 'KOA' or 'HAPI' which have support for node http2. This might be useful for you
Also, Read this Release 5.0#2237. It says that:
The goal of Express 5 is to be API tweaks & the removal of all code
from the Express repository, moving into components in the pillarjs
project (https://github.com/pillarjs), providing at least basic
support for promise-returning handlers and complete HTTP/2
functionality. Express 5 would become a "view into pillarjs" and would
be an arrangement of these components.

Resources