I want to perform a realtime crud using vuex, node, express and socketio but using the following syntax I can't get the result.
Server
index.js
const server = app.listen('3000',() => {
console.log('<--- Web Server Starter --->')
const io = require('./sockets')(server)
io.on('connection', socket=>{
console.log('client connected');
})
})
socket.js
let io
module.exports = {
init:httpServer =>{
io = require('socket.io')(httpServer)
return io
},
getIo:()=>{
if(!io){
throw new Error('socket io not initialized')
}
return io
}
}
user.js
const io = require('../socket')
router.post('/newuser',(req, res) => {
res.json({ serverResponse: 'userCreated' })
io.getIo().emit('newuser',{serverResponse:'created',user:user})
})
Client
Module user.js (VUEX actions)
getusers({ commit }){
const sessionToken = localStorage.getItem('sessionToken')
axios.get('/newuser', {
headers: {
Authorization: `Bearer ${localStorage.getItem('sessionToken')}`
},
})
.then(response => {
const socket = openSocket('http://localhost:3000')
socket.on('newuser', data => {
if (data.serverResponse === 'created') {
this.users = data.user
commit('GET_USERS', users)
})
})
.catch(error => {
alert(error)
})
})
When I create the new user, the user list is not updated automatically, but I have to refresh the page to see the new user, why does this happen?
This is because in your backend you are handling the post url-endpoint '/newuser' to get the data. You are not actually posting the data using socketio, therefore if you don't update the page, your axios.get function isn't going to have any new data to get until the API you are posting to has refreshed. It would be better to put your socket client code outside of the axios promise so that the data is primarily updated on the client by socketio and not by the API.
EDIT:
This is the code for it in your client
getusers({
commit
}) {
const sessionToken = localStorage.getItem('sessionToken')
axios.get('/newuser', {
headers: {
Authorization: `Bearer ${localStorage.getItem('sessionToken')}`
},
})
.then(response => {
console.log('success');
})
.catch(error => {
alert(error)
})
const socket = openSocket('http://localhost:3000')
socket.on('newuser', data => {
if (data.serverResponse === 'created') {
this.users = data.user
commit('GET_USERS', users)
})
})
You had a problem with your .catch part of the promise as it was inside the .then part and I also moved your socket code outside of the promise.
So in your server when you post to /newuser. you send emit from the socketio
on your client you dont need to use axios to check if some socket events has been fired, try to remove the axios.get() and keep
const socket = openSocket('http://localhost:3000')
socket.on('newuser', data => {
//do some thing
})
Related
I'm trying to send an event if there is a request from controller.
using websocket ws:
// openWSConnection
const wsServer = new WebSocketServer({
port: '8080'
})
const publish = (data) => {
return data
}
const testSend = (socket) => {
publish({}, (err,data) => {
socket.send(data)
})
}
wsServer.on('connection', function (socket) {
testSend(socket)
})
module.exports = {
publish
}
In controller
router.post("/create", async (req, res, next) => {
openWSConnection.publish(
{
toUser_id,
type,
status,
title,
subtitle,
description,
})
})
Every time the create will triggered, Websocket are not able to send the data to the client.
I'm trying to make it work like, If there are events that is being created it will send the data to websocket and pass it to the client.
Thanks for the help!
I'm using MERN stack for a project. I want to hide my api endpoints on the frontend when I call them. I'm now making a request from React like so:
useEffect(() => {
axios
.get("https://MY_API_URL/posts") // MY_API_URL is the url that I want to hide
.then((res) => {
dispatch(setCurrentUser(res.data));
})
.catch((err) => {
console.log(err);
});
});
This is how I'm GETing the posts from the expressjs:
controllers/posts.js
const Post = require("../models/post");
const getPosts = async (req, res) => {
try {
const post = await Post.find();
res.status(200).json(post);
} catch (err) {
res.status(404).json({ message: err });
}
};
I want to make the request to the url from the backend so that my API is hidden in the client.
This is what I have tried in the frontend:
useEffect(() => {
axios
.get("http://localhost:3000/posts")
.then((res) => {
dispatch(setCurrentUser(res.data));
})
.catch((err) => {
console.log(err);
});
});
And my backend now looks like this but it doesn't work. I also have removed the Posts.find() inside the request, I'm not sure if it is still necessary or how am I going to use this?
controllers/posts.js
const getPosts = async (req, res) => {
try {
const response = await axios.get(
"https://MY_API_URL/posts"
);
const posts = response.data;
console.log(posts);
res.status(200).json(posts);
} catch (err) {
res.status(404).json({ message: err });
}
};
On localhost it works fine, but when I push my code to github and deploy it, it doesn't work on the deployed version then in the localhost it also stops working.
Error message on console:
GET http://localhost:3000/posts 404 (Not Found)
As the title suggest, I get a weird error when responding with data from my server.
In homepage.js (which I want to load after loggin in) I have this request to the server to get the posts and then set the posts to the response.
useEffect(() => {
//userService.getDashboard() === Axios.get('http://localhost:3001/homepage')
userService.getDashboard().then((response) => {
setListOfPosts(response)
});
}, []);
This request first goes to the homepage.js, which further sends a request to getPosts, like so:
const headers = req.headers;
const getPosts = Axios.get('http://localhost:3001/getPosts', {headers: headers});
getPosts.catch((response) => {
//NEVER GET ANY RESPONSE???
console.log('Error in homepage.js')
//res.send(response);
});
getPosts.then((response) => {
//NEVER GET ANY RESPONSE???
res.send(response.data);
});
And lastly in the chain I have the getPosts router which does:
router.get('/', authenticateToken, async (req, res) => {
await db.query('SELECT * FROM posts',
(err, result) => {
if (err) {
console.log('HELLO FROM ERROR')
res.send({errorMessage: err});
} else {
console.log(result)
res.send(result);
}
});
});
So I can confirm that after every request to homepage I get all the way to getPosts() and the database query always works fine and goes into the result where "console.log(result)" lies and I can confirm that the result is indeed all the posts. The weird stuff happens when I'm sending back the data. So from getPosts() I'm obviously doing a res.send(result) which sends the data back to homepage.js. But this is when I get the error "UnhandledPromiseRejectionWarning: Error: Request failed with status code 304"
Any idea why?
you should not use res.send inside the .then of axios
this code works for me
useEffect(() => {
getPosts.then((response) => {
console.log("inside getPosts.then ");
console.log(response);
});
and this is my controller file to send request to backend:
const axios = require("axios");
export const getPosts = axios.get("http://localhost:5000/tasks/taskscheck");
getPosts.catch((response) => {
console.log("Error in homepage.js");
});
getPosts.then((response) => {
console.log("inside then get posts");
console.log(response);
});
I have tasks project and I can see in the response all my tasks.
I'm building an web app to receive data from an api using nodejs as backend, and show this data on the client side using React. But it's my first time using socket.io.
Sockets.ts
function socket( io ){
io.on("connection", socket => {
var socketId = socket.id;
var clientIp = socket.request.connection.remoteAddress;
console.log('New connection ' + socketId + ' from ' + clientIp);
socket.on("disconnect", () => {
console.log("Client disconnected");
});
});
}
export default socket;
router.controller.ts
export const getData: RequestHandler = async (req, res) => {
const options= {
method: 'GET',
};
const response = await fetch(citybikeurl, options)
.then((res: any) => res.json())
.catch((e: any) => {
console.error({ error: e });
});
console.log("RESPONSE: ", response);
res.json(response);
}
routes.ts
router.get('/', dataController.getData)
At the moment, I don't know if I'm passing any data from controller.ts to Sockets.ts, and after of this be able to emit the results.
You should be using a socket on the server-side as well.
Please refer to this guide for how to set up a socket server:
https://medium.com/#raj_36650/integrate-socket-io-with-node-js-express-2292ca13d891
I am learning about these technologies (React JS, Node, WebSockets) and working on a project that uses websockets to display information on graphs in real time.
I have a state in my component that stores an array of objects with different attributes.
When I make a POST request to my server the record is saved in the database (Made in PostgreSQL) and I notify the client to do the update
My problem is that when I refresh the page it stops working and I need to restart the server to be able to see the changes in the graph again.
SERVER
io.on('connection', client => {
app.post("/registros/nuevo", async (req, res) => {
try {
let insertar = await pool.query(`INSERT INTO registro
(fecha, hora, temperatura, presion, humedad, viento, viento_max, radiacion, precipitacion)
VALUES
('${req.body.fecha}', '${req.body.hora}', ${req.body.temperatura}, ${req.body.presion},
${req.body.humedad}, ${req.body.viento}, ${req.body.viento_max}, ${req.body.radiacion},
${req.body.precipitacion});`).then(() => { client.emit('new: data', 'updated') });
res.json({ message: "Recibido" });
} catch (err) {
console.error(err.message);
}
});
});
CLIENT
const [data, setData] = useState([])
const getData = async () => {
try {
const response = await fetch("http://localhost:5000/registros");
const jsonData = await response.json();
setData(jsonData);
setCurrent(jsonData[jsonData.length - 1])
} catch (err) {
console.error(err.message)
}
};
useEffect(() => {
getData()
}, [])
useEffect(() =>{
socket.on('new: data', (c) =>{
console.log(c)
getData()
})
}, []);
I know that my code isn't the best, and thank u for ur help
I got the solution, my mistake was put the request inside of socket body
app.post("/registros/nuevo", async (req, res) => {
try {
let insertar = await pool.query(`INSERT INTO registro
(fecha, hora, temperatura, presion, humedad, viento, viento_max, radiacion, precipitacion)
VALUES
('${req.body.fecha}', '${req.body.hora}', ${req.body.temperatura}, ${req.body.presion}, ${req.body.humedad}, ${req.body.viento}, ${req.body.viento_max}, ${req.body.radiacion}, ${req.body.precipitacion});`)
io.emit('new: data', 'Actualizado')
res.sendStatus(204)
} catch (err) {
res.sendStatus(500)
}
});