I'm running a React/Node/MariaDB setup, where my Node acts as a getter and setter to my database depending on front end events. So I have React polling Node every 2 seconds to get a value called selectorPos or selPos in some cases. This value needs to be kept up to date with the database value, but also needs to be able to be changed by the GUI components. So I have a button press set to update the value in the database, then it would be read and updated upon the 2 second polling.
My solution works perfectly for a few button clicks. But seemingly randomly it will hang after a database write and nothing else works. Once I force stop the node server and restart, it rapid prints out a bunch of console.log statements I had set up for polling and writing, as if it had a backlog to catch up on, then it works again until another hang and reset.
I feel like there is something quite minor I am overlooking here. The code works, but it seems to get overloaded quite easily.
Here is my code:
React stuff:
componentDidMount() {
this.interval = setInterval(()=> this.getSelPos(), 2000);
}
componentWillUnmount() {
clearInterval(this.interval)
}
getSelPos() {
axios.get("http://localhost:5000/selector", { crossdomain: true }).then(response => {
console.log(response.data);
this.setState({SelectorPos: parseInt(response.data)});
console.log("Selpos is" + selPos);
});
}
setSelPos(i) {
axios.post("http://localhost:5000/selector", { position: i }).then((response) => {
console.log(response);
}, (error) => {
console.log(error);
});
}
handleClick(i){
this.setSelPos(i);
Node:
const express = require('express')
const db = require('./db')
const app = express()
const port = 5000
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
// GET
app.get('/selector', async (req, res) => {
try {
const result = await db.pool.query("select value from db.tags where tag='1006'");
res.send(result[0].value.toString());
console.log(result[0].value.toString());
} catch (err) {
throw err;
}
});
// POST
app.post('/selector', async (req, res) => {
try {
const result = await db.pool.query("update db.tags set value = " + req.body.position.toString() + " where tag='1006'");
console.log(result);
} catch (err) {
throw err;
}
});
app.listen(port, () => console.log(`Listening on port ${port}`));
Related
I made get request to Serp api, but learned that it is not possible to directly make fetch to Serp from React application, so I created local server and wrote logic for it, then I tested it with Postman and everything is fine. Then I had problems with CORS, I(guess) fixed them, but now I receive rejected promise on response and can't get rid of this. It gives
Unexpected end of input
Here is my server:
const SerpApi = require('google-search-results-nodejs');
const search = new SerpApi.GoogleSearch("myApiKey");
const express = require('express');
const app = express();
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.get('/:id', function (req, res) {
console.log("Made request");
const searchText = req.params.id;
const params = {
q: searchText,
tbm: "shop",
};
const callback = function (data) {
const objects = [...data["shopping_results"]];
console.log("call back worked");
if (!objects) {
console.log("ERROR 404");
res.status(404).send();
}
res.status(200).send(objects);
};
// Show result as JSON
search.json(params, callback);
});
app.use(allowCrossDomain);
app.listen(3001, function () {
console.log("App is listening for queries");
})
and my fetch:
import updateOnSearchRequest from '../redux/actions/updateOnSearchRequest';
export default function searchRequestToApi(queryText, dispatch) {
fetch(`http://localhost:3001/${queryText}`, {
mode: 'no-cors',
})
.then(res => console.log(res.json()))
.then(data => data ? dispatch(updateOnSearchRequest(data)) : {});
}
I receive error at console.log(res.json()) even though server works fine and doesnt give any errors
First of all, you need to remove mode: "no-cors", as mentioned in this answer, using it will give you an opaque response, which doesn't seem to return data in the body.
Second, move your app.use(allowCrossDomain); to the top so it's higher than app.get("/:id", function (req, res) {....
And lastly, you must remove console.log from .then(res => console.log(res.json())).
In summary, your server should be:
const SerpApi = require("google-search-results-nodejs");
const search = new SerpApi.GoogleSearch("myApiKey");
const express = require("express");
const app = express();
var allowCrossDomain = function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type");
next();
};
app.use(allowCrossDomain);
app.get("/:id", function (req, res) {
console.log("Made request");
const searchText = req.params.id;
const params = {
q: searchText,
tbm: "shop",
};
const callback = function (data) {
const objects = [...data["shopping_results"]];
console.log("call back worked");
if (!objects) {
console.log("ERROR 404");
res.status(404).send();
}
res.status(200).send(objects);
};
// Show result as JSON
search.json(params, callback);
});
app.listen(3001, function () {
console.log("App is listening for queries");
});
And your fetch should be:
fetch(`http://localhost:3001/${queryText}`)
.then(res => res.json())
.then(data => data ? dispatch(updateOnSearchRequest(data)) : {});
const express = require("express");
const expressAsyncHandler = require("express-async-handler");
const app = express();
const f = async () => {
return false;
};
app.get(
"/",
expressAsyncHandler(async () => {
throw await f();
}),
() => {
console.log("the bug!");
}
);
app.use((err, req, res, next) => {
console.log("caught!", err);
});
app.listen(4000, () => console.log("listening on port 4000..."));
Expected output on the console:
"caught!".
output:
the bug!.
question: Why? Is it a bug in async-express-handler package or is it a normal JavaScript behaviour? what if I want to throw await something inside? how ?
Your problem is that you're throwing the value false. This doesn't fit into nodejs' callback conventions (and by extension, express error handling), which requires the err parameter to get a truthy value to be considered an error. A much simpler way to reproduce the issue:
app.get(
"/",
(req, res, next) => {
Promise.reject(false).catch(next);
// or even just:
next(false);
},
() => {
console.log("the bug!");
}
);
So just don't do that! Always throw an Error, not a string, not something else, and this principle also holds for promise rejections.
I Am developing a Node API for employee department model
for which i developed couple of Request Like 'GET PUSH PATCH DELETE' (CRUD Operation)
for both end employee & department
i am developing on my local server
here's my app.js looks like
const http=require('http');
const app =require('./app');
const port =process.env.PORT || 3000;
const server = http.createServer(app);
server.listen(port);
console.log('Server Has Been Started');
console.log('localhost:'+port);
And On the listner side here's my app.js looks like
// Dependency
const express = require('express');
const app = express();
const morgan =require('morgan');
const bodyParser =require('body-parser');
const mongoose =require('mongoose');
// Importing routes
const employeeRoutes =require('./api/routes/employee');
const departmentRoutes =require('./api/routes/department');
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
// Header Defination to Avoid Corp's
app.use((req, res ,next) =>
{
res.header("Access-Control-Allow-Origin","*");
res.header(
"Access-Control-Allow-Headers",
"Origin,X-Requested-With,Content-Type,Accept,Authorization"
);
if (req.method === 'OPTIONS')
{
res.header('Access-Control-Allow-Methods','PUT,POST,PATCH,DELETE,GET');
return res.status(200).json({});
}
});
// Routes for api
app.use('/employee',employeeRoutes);
app.use('/department',departmentRoutes);
// Error Handling
app.use((req, res, next) =>
{
const error =new Error('Not Found');
error.status =404;
next(error);
});
app.use((error, req, res, next) =>
{
res.status(error.status ||500);
res.json({
error:{
message:error.message
}
});
});
module.exports = app;
in order to send request and receiving response as a json on other end
i developed employee .js and department .js with GET PUSH PATCH DELETE
here's my both file looks like
./api/routes/employee.js
it just showcase script to validate code is working or not
const express = require('express');
const router =express.Router();
const mongoose =require('mongoose');
const Employee =require('../models/Employee');
router.get('/',(req, res ,next) => {
res.status(200).json({
message:'Handling GET request to ./employees'
});
});
router.post('/',(req, res ,next) => {
res.status(201).json({
message:'Handling POST request to ./employees',
});
});
router.get('/:employeeId',(req, res ,next) =>
{
const id =req.params.employeeId;
if (id === 'special'){
res.status(200).json({
message: 'You Discovered A speacial ID',
id:id
});
} else
{
res.status(200).json({
message:'You passed an ID'
});
}
});
router.patch('/:employeeId',(req, res ,next) =>
{
res.status(200).json({
message:'Updated Employees'
});
});
router.delete('/:employeeId',(req, res ,next) =>
{
res.status(200).json({
message:'Deleted Employee'
});
});
module.exports =router;
../api/routes/department.js
const express = require('express');
const router =express.Router();
router.get('/',(req, res ,next) =>{
res.status(200).json({
message:'Department fetched'
});
});
router.post('/',(req, res ,next) =>{
const department={
name:req.body.name,
Id:req.body.Id
};
res.status(201).json({
message:'Department created',
createdDepartment:department
});
});
router.get('/:departmentId',(req, res ,next) =>{
res.status(200).json({
message:'Department Details',
departmentId: req.params.departmentId
});
});
router.delete('/:departmentId',(req, res ,next) =>{
res.status(200).json({
message:'Department Deleted',
departmentId: req.params.departmentId
});
});
router.patch('/:departmentId',(req, res ,next) =>
{
res.status(200).json({
message:'Department Updated',
departmentId :req.params.departmentId
});
});
module.exports =router;
Now when i try to run this code in as permy coding experience it has no logical error
also on terminal it showed
terminal o/p
but when i try to run in postman
it just loading not response is coming back
likepostman o/p
and also on web like
web o/p
and then onto terminal be like
terminal after get not respond still server is running
i know there is problem with connection but i double check all the possible way like proxy and firewall disabled
also i tried to delter node module and package.json(lock) and reinstalled it nothing of them is working
and when i stop the server postman show socket hangup
sockethangup postman
i wanna to know where i am lacking with meaninf ful answer
Add next() to pass the request to the next middleware after the CORS section.
// Header Defination to Avoid Corp's
app.use((req, res ,next) =>
{
res.header("Access-Control-Allow-Origin","*");
res.header(
"Access-Control-Allow-Headers",
"Origin,X-Requested-With,Content-Type,Accept,Authorization"
);
if (req.method === 'OPTIONS')
{
res.header('Access-Control-Allow-Methods','PUT,POST,PATCH,DELETE,GET');
return res.status(200).json({});
}
// Pass next middleware
next();
});
I was trying to make a routes for each ID I using a forEach loop but It stay loading until timeout reaches, all expected values are in place, all good but the second route is not running, I was fighting it despretly until now. I made sure there is a problem.
server.js
const router = require('express').Router();
function isAuthorized(req, res, next) {
if (req.user) {
next();
}
else {
res.redirect('/login')
}
}
let myguild = [];
router.get(`*`, isAuthorized, (req, res) => {
res.status(200);
console.log("wow");
console.log(req.user.guilds.length)
req.user.guilds.forEach(guild => {
myguild.push(guild);
})
console.log("Finished");
myguild.forEach(guild => {
console.log('Started')
router.get(guild.id, (req, res) => { // here is the problem
console.log("uh")
res.send("HAMBURGER")
console.log(req, res, guild)
})
console.log("Outed")
})
});
module.exports = router;
output:
wow
23
Finished
Started
Outed
Started
Outed
Started
Outed
Star... 'there is more but this is enough'
It should behave and run within server/${guild.id} but got (failed) request
Any Ideas?
You might need to redesign the API to better fit what you're trying to accomplish. If you already know which guilds are available then you'd need to create those before the server is initialized.
Even if they come from a database or are dynamic, you can loop through the guild "options" and create endpoints then provide access to them only if the user is qualified.
const { guilds } = require('./config')
const guildHandler = (req, res) => {
// Assuming you're doing more here
res.send('Hamburger')
}
guilds.forEach(guild => router.get(`/guilds/${guildId}`, guildHandler)
Or if you are NOT doingg something different in the middleware for each guild then you could just have a single route for guild.
router.get('/guilds/:guildId, guildHandler)
Not really sure what you're trying to accomplish but checkout out the Express docs. They solve most use cases fairly easily.
https://expressjs.com/en/api.html#req
You never call res.end() from your outer res.get() handler, so the request never completes.
And, with respect, creating route handlers like that in a loop is a mistake. It will lead to real performance trouble when your app gets thousands of guilds.
You'll want to use just one route, with a named route parameter, something like this.
const createError = require('http-errors')
router.get(':guildid', isAuthorized, (req, res, next) => {
const guildid = req.params.guildid
if (req.user.guilds.includes(guild)) {
console.log("uh")
res.send("HAMBURGER").end()
console.log(req, res, guildid)
} else {
next(createError(404, guildId + ' not found'))
}
})
Thanks for everyone helped.
Inspired answer
Final Result:
server.js
router.get('/:guildid', isAuthorized, (req, res, next) => {
console.log('started')
const guildid = req.params.guildid
if (req.user.guilds.some(guild => guild.id === guildid)) {
console.log('uh')
res.send("HAMBURGER").end()
} else {
res.sendStatus(404);
}
})
I've created a simple next.js application and provide it with a backend of express.js, now all I want is whenever someone visits the site a hit should originate on the server and the server should communicate the number of hits back to next.js application. The code of server.js file goes here:
const express = require("express");
const next = require("next");
var counter = 0;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get("*", (req, res) => {
counter++;
return handle(req, res);
});
server.listen(3000, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
as seen here I've set counter variable to zero and want it to be increased whenever a get request is made (so wrote counter++ inside server.get function) but how could I display this number of hits on the route visitor is visiting?
You can use express's res.locals in order to pass the data on the request object.
app
.prepare()
.then(() => {
const server = express();
server.get('*', (req, res) => {
counter++;
res.locals.counter = counter;
//----^
return handle(req, res);
});
server.listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
Then this request object will be available in getInitialProps of the page that is needed.
// some-page.js
const Page = ({ counter }) => <div>{counter}</div>;
Page.getInitialProps = ({ req, res }) => {
if (res) {
// this means that you are on the server
return { counter: res.locals.counter };
}
return {};
};