I'm working on building an inventory management application using PERN stack. I have a modal where I need to make 2 GET requests and when I console.log in front end both requests are getting Status 200 response. However in my express server, first get request is working fine but the second request is not receiving anything.
My frontend code
const openModal = async () => {
setDetailModalOpen(true)
try {
await Promise.all([
(async () => {
const serial_number = props.bacsSerial
const response = await fetch(`http://localhost:5000/bacslist/demoinventory/${serial_number}`)
const parseResponse = await response.json()
console.log(response)
setInputs({
bacsUnit: parseResponse.bacs_unit,
serialNumber: parseResponse.serial_number,
partNumber: parseResponse.part_number,
bacsLocation: parseResponse.bacs_location,
description: parseResponse.bacs_description
})
setBacsId(parseResponse.id)
setBacsData(parseResponse)
})(),
(async () => {
const response2 = await fetch(`http://localhost:5000/bacslist/demoinventory/${bacsId}`)
console.log(response2)
})()
])
} catch (err) {
console.error(err.message)
}
}
My backend code
router.get("/demoinventory/:serial_number", async (req, res) => {
console.log('This one is working')
try {
const {serial_number} = req.params
const getDemoBacs = await pool.query(
"SELECT * FROM demo_inventory WHERE serial_number = $1", [serial_number]
)
res.json(getDemoBacs.rows[0])
} catch (err) {
console.error(err.message)
}
})
router.get("/demoinventory/:bacsId", async (req, res) => {
console.log(req.params)
console.log('This one is not working')
try {
const getHistoryData = await pool.query(
"SELECT * FROM demo_inventory_history"
)
console.log(getHistoryData)
res.json(getHistoryData)
} catch (err) {
console.error(err.message)
}
})
Sorry, Kinda new to this stuff so this isn't exactly an answer but I'm not allowed to leave a comment. I can't see your state variables with the code you posted, but are you sure that BacsId is being set to state before it is used in the second call, or is the parameter in the second call being sent empty, thus not using the right URL? Just a thought.
Related
I want to add data to my MongoDB collection. I'm getting this data via a local Flask API. I'm GETting the data on my React Frontend and it's displaying fine. I'm not sure why I can't do the same thing on my express nodejs backend. I want to get that same data and use it to build the entity that I'm going to store.
This is how I'm attempting to get the data
app.get('/', async (req, res) => {
let initialData = {};
axios.get('http://localhost:3000/details').then((res) => {
initialData = res.data;
});
const recruit = new RecruitModel({ email:initialData.email,
mobile_number:initialData.mobile_number,
name:initialData.name});
try {
await recruit.save()
res.send("inserted data")
} catch (error) {
console.log(error)
}
})
I'm pretty sure something wrong there and nowhere else. Because if I pass static information instead it's correctly stored, no issues.
You are saving to the database's Recruit Collection before the promise is resolved. Since data to save in the Recruit Collection is dependent upon the result from the API which will initially return the promise, therefore, use promise resolving functions to wait for its result.
Solution#1 (using .then function):
app.get('/', async (req, res) => {
let initialData = {};
try {
axios.get('http://localhost:3000/details').then((response) => {
initialData = response.data;
const recruit = new RecruitModel({
email: initialData.email,
mobile_number: initialData.mobile_number,
name: initialData.name,
});
recruit.save().then((response) => res.send('inserted data'));
});
} catch (error) {
console.log(error);
}
});
Solution#2 (using async await keywords):
app.get('/', async (req, res) => {
try {
const response = await axios.get('http://localhost:3000/details');
const recruit = new RecruitModel({
email: response.data.email,
mobile_number: response.data.mobile_number,
name: response.data.name,
});
await recruit.save();
res.send('inserted data');
} catch (error) {
console.log(error);
}
});
Either solution will work in your case.
I got trouble when creating API using axios. The new array received no contain data but when I run console.log(response), it shows data (see image attach). Anyone can help me for this issue
router.get('/', async (req, res) => {
const pools = [
'pool1',
'pool2',
]
const poolList = pools.map(async pool => {
const response = await axios.get(`https://example.com/pools/${pool}/summary.json`)
console.log(response)
return {
response
}
})
res.send({
poolList
})
})
enter image description here
Problem
Your poolList is an array of promises. You're then trying to respond with these promises as JSON. This will look something like the following because when promises are stringified, they become empty objects
{
"poolList": [{}, {}]
}
Solution
What I suspect you actually want is the following...
router.get('/', async (req, res) => {
const pools = [
'pool1',
'pool2',
]
try {
const poolList = await Promise.all(pools.map(async pool => {
const { data } = await axios.get(`https://example.com/pools/${encodeURIComponent(pool)}/summary.json`)
return data // resolve with the data, not the full Response object
}))
res.json({ poolList })
} catch (err) {
console.error(err)
res.status(500).send(err)
}
})
This creates an array of promises that resolve with the remote data (each summary.json) and waits for each of those promises, resulting in an array of data.
This will respond with something like
{
"poolList": [
{ /* pool1/summary.json */ },
{ /* pool2/summary.json */ }
]
}
Its because of async in pools.map(async pool => {. The expected
result of poolList is an array of promises.
try to await all
const pools = [
'pool1',
'pool2',
]
const poolList = await Promise.all(pools.map(async pool => {
const response = await axios.get(`https://example.com/pools/${pool}/summary.json`)
console.log(response)
return {
response
}
}));
res.send({
poolList
})
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)
}
});
I would happy for your help
I'm trying to use firebase on nodejs server.
after initial configurations I build a rest on node server that used to fetch data from firebase database
Here is the first version of the code
app.get('/api/users/:id', (req,res) =>{
const usersRef = firebase.database().ref('users');
usersRef.once('value')
.then((snapshot) => {
console.log(snapshot);
res.status(200).send(snapshot.val())
})
.catch((error) => {
console.log(error);
res.status(404).send(error.message)
})
}))
I've checked the route with postman and found that I didn't received any response from that route
I've check with logs that the route received the request and I found that I must create async call to database, so, I created middleware
And here is the new version of code:
const asyncMiddleware = fn =>
(req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(next);
};
app.get('/api/users/:id', asyncMiddleware(async (req,res,nex) =>{
const usersRef = firebase.database().ref('users');
await usersRef.once('value')
.then((snapshot) => {
console.log(snapshot);
res.status(200).send(snapshot.val())
})
.catch((error) => {
console.log(error);
res.status(404).send(error.message)
})
}))
But the problem continue even after the changes.
So I found that the reason for the problem is because the 'once' function stack when he tried to fetch data from firebase and not return any response.
I would really like to your help here
thanks
I guess it has to do with the way you handle the asynchronous requests. Try the code below and let's see if we'll get any luck.
const fetchUsers = () => new Promise((resolve, reject) => {
try{
const usersRef = firebase.database().ref('users')
usersRef.once('value', (snapShot) => {
resolve(snapShot)
})
}catch(err){
reject(err)
}
})
app.get('/api/users/:id', async (req,res) =>{
const users = await fetchUsers()
/**
* clean the users response
* and respond with data
*/
res
.status(200)
.json({
data: users //cleaned
})
}))
So, After Investigate I found a solution for this problem.
I've used axios on server send request by using REST API of firebase
https://firebase.google.com/docs/reference/rest/database
I need to test if my POST request to my endpoint works properly with a Jest test. I had the idea of first getting the count of my Services table (I'm using sequelize orm), then to send a new post request and to finally get the new count and compare if the old count + 1 will equal to the new count, if true then the POST request works just fine.
test('Create a valid Service', async (done) => {
const service = {
name: "cool",
description: "description"
};
await Service.count().then(async function (count) {
await request(app)
.post('/api/services')
.send(service)
.then(async () => {
await Service.count().then(function (newcount) {
expect(newcount).toBe(count + 1);
});
})
.catch(err => console.log(`Error ${err}`));
});
});
For me the test looks fine, but when I run it I get:
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
Is something missing or is there even a better way to test a POST request? with Jest?
It is because you are not calling the done callback passed in jest callback function. It can be done like this.
test('Create a valid Service', async(done) => {
const service = {
name: "cool",
description: "description"
};
await Service.count().then(async function (count) {
await request(app)
.post('/api/services')
.send(service)
.then(async() => {
await Service.count().then(function (newcount) {
expect(newcount).toBe(count + 1);
// execute done callback here
done();
});
})
.catch(err => {
// write test for failure here
console.log(`Error ${err}`)
done()
});
});
});
You can also write this code in this way so that the readability can be improved and maximize the use of async/await.
test('Create a valid Service', async(done) => {
const service = {
name: "cool",
description: "description"
};
try {
const count = await Service.count();
await request(app).post('/api/services').send(service)
const newCount = await Service.count()
expect(newCount).toBe(count + 1);
done()
} catch (err) {
// write test for failure here
console.log(`Error ${err}`)
done()
}
});
By default Jest also resolves the promise in async/await case. We can achieve this without the callback function also
test('Create a valid Service', async() => {
const service = {
name: "cool",
description: "description"
};
try {
const count = await Service.count();
await request(app).post('/api/services').send(service)
const newCount = await Service.count()
expect(newCount).toBe(count + 1);
} catch (err) {
// write test for failure here
console.log(`Error ${err}`)
}
});