Getting empty array from get - javascript

When i'm going to localhost:3000/api/categories i'm getting an empty array, but when i log my products there is alot of data inside the object. Anyone knows what i'm doing wrong? Thanks!
let products = getData()
function getData() {
return fetch('some url',
{
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
).then(res => res.json())
};
app.get(('/api/categories'), (req, res) => {
products.then(console.log);
res.send(products);
products.then(console.log);
});

products is a promise. You can't send it to the client via res.send.
Instead, do what you're doing when you log it: use then:
app.get(('/api/categories'), (req, res) => {
products
.then(data => res.send(data))
.catch(error => {
// Send an error
});
});
Note that your code gets the products once, at startup, and then responds to the request with that static set of products.
If you want to get the products in response to the request from the client, remove the
let products = getData();
and put it in the get handler:
app.get(('/api/categories'), (req, res) => {
this.getData()
.then(data => res.send(data))
.catch(error => {
// Send an error
});
});
That repeats the request each time the client calls your server.
Of course, you might consider a middle ground, keeping and reusing the data for X seconds...

Related

No matter how I set the res.format() in Express, the data is always parsed depending on the parse method of fetch(). Why?

I am not understanding how does the res.format() work. I read all the documentation, plus several answers here on stackoverflow, but they don't actually address the part that confuses me.
app.get('/', (req, res) => {
res.format({
'text/html' : function() {
res.send({name: 'romeo'})
}
})
})
In the above example, I am setting the format to be 'text/html', but I am actually sending a JS object.
So, now, in the client side:
fetch(req)
.then(res=>res.json())
.then(content=> {
//output.innerHTML = JSON.stringify(content, '\n', 2);
console.log(content)
output.innerHTML = content;
})
.catch(err=>console.eror);
If I use json(), the data will just get parsed into a JS object no matter what I send, and no matter what I set the res.format() to be. Why? This is what I don't get.
Even if I set the format to be 'application/json', I can just send a plain text, and then if I use json() again, it will again return a JS object.
And vice versa, if I send a JS object, but use text() instead, it will get parsed into text.
So, what exactly does the format do?
Yes, I read that It's supposed to check the Accept in the HTTP request header, and then invoke corresponding handler according the Accept value, but that doesn't really tell me anything. I am not setting a request header, and no matter how I set the format(), the actual format of the data is always determined by the parsing method I choose to use json() for JS object, or text() for text or html. I don't see the purpose of setting a format().
res.format(object) is used such that the client can specify what type of content they want returned. The client specifies this information using the Accepts header on their request.
To read more about res.format(object) visit https://expressjs.com/en/5x/api.html#res.format
To read more about the Accepts header visit https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept
Below I created a simple example of what this would look like
Server code
const express = require("express");
const PORT = process.env.PORT || 5000;
const app = express();
app.get('/', function (req, res) {
res.format({
'text/plain': function () {
res.send('text')
},
'text/html': function () {
res.send('<p>html</p>')
},
'application/json': function () {
res.send({ message: 'json' })
},
})
})
app.listen(PORT, () => {
console.log("Listening on port: " + PORT);
});
Client Code
const fetch = require("node-fetch");
fetch('http://localhost:5000/', {
headers: {
'Accept': 'text/html'
}
})
.then(res => res.text())
.then(res => {
console.log(res) // <p>html</p>
});
fetch('http://localhost:5000/', {
headers: {
'Accept': 'text/plain'
}
})
.then(res => res.text())
.then(res => {
console.log(res) // text
});
fetch('http://localhost:5000/', {
headers: {
'Accept': 'application/json'
}
})
.then(res => res.json())
.then(res => {
console.log(res) // { message: 'json' }
});

Why Axios response doesn't console log result?

I'm working on an backend API but at some point I need to get user data from another API. I am trying to use Axios to make http request in order to do that. The request return the result in the browser as expected but the problem is that I can't display console log in the terminal. It doesn't show anything even though I asked the program to do so. Is there a problem probably with my code?
Here is my code :
const axios = require('axios');
const AxiosLogger = require('axios-logger');
const instance = axios.create();
module.exports = (router) => {
router.get('/profile', function(req, res) {
//random fake profile info
axios.get('https://randomuser.me/api/')
.then(response => {
console.log(response.data);
console.log(response.data);
return response.data
})
.catch(error => {
console.log(error);
});
});
};
I would suggest trying response.send to forward the axios response to your client like so:
module.exports = (router) => {
router.get('/profile', function(req, res) {
//random fake profile info
axios.get('https://randomuser.me/api/')
.then(response => {
console.log(response.data);
// Send the axios response to the client...
res.send(response.data)
})
.catch(error => {
console.log(error);
});
});
};

How to globally activate useEffect in React?

I am creating a chat application in React. I am using the useEffect-hook to update the messages (all it really does is fetch them from the JSON-server). I want them to be updated every time someone in the room sends a new message.
This is one alternative I have:
useEffect(() => {
fetch('http://localhost:8000/messages/')
.then(res => {
return res.json();
})
.then(data => {
data = data.filter((msg) => msg.room === room);
setData(data);
})
.catch(err => {
console.error(`Error: ${err}`);
})
divRef.current.scrollIntoView({ behavior: 'smooth' });
}, []);
"data" is a list of messages. This shows all the messages when you enter the room, but does not load when you pass a new message. Assumingly because of the empty list at the end. Therefore I tried this:
In another component, I have a variable "sent", which is set to true every time you send a message, like this:
const onSubmit = (e) => {
e.preventDefault();
const data = {author: user, body: msg, room }
setSent(true);
fetch(`http://localhost:8000/messages/`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
})
.then(response => {
response.json();
setSent(false);
})
.catch(err => console.error(`Error: ${err}`));
setMsg('');
}
So every time you send a message, it is set to 'true', and as soon as it has been successfully sent, it is set back to 'false'. I then passed it as a prop to the component I use useEffect:
<div className='chat-main'>
<Messages user={user} room={room} sent={sent} />
</div>
Then I put the "sent"-variable in the list at the bottom of the useEffect-hook. This updates the messages for the user who sends a message, but not for the others (because, of course, "sent" only changes if you send a message)
What can I do here? Is there a way?

JavaScript express, node and CSVtoJSON

I'm currently developing a 'Dupe Finder' web app for a co-worker. This is my first time using the 'csvtojson' package.
I'm reading from the file just fine on the server, but when I send a response back to the client (ideally containing a json object) I'm getting this very odd console log and I'm not sure if its correct:
To get this response, I have a button on the home page, when clicked, the client makes an http request on the home directory of the server, called '/getnums'. The request reads from the CSV then should be returning and obj with its contents. It is sort of doing that, in the screenshot, if I click the tick next to promiseValue, it'll give me an array. But i'm not sure why its returning a Promise..anyway..
api.js:
var CSVDATA = () => {
fetch('/getnums')
.then(res => {
console.log(res.json())
})
}
export default {
CSVDATA,
}
'/getnums' goes to my router, which is simly router.get('/', mainController.getNums)
in the controller is where the reading begins:
const csv = require('csvtojson')
module.exports = {
getNums: (req, res, next) => {
const csvFilePath = `${__dirname}/../../client/readFrom/main.csv`
csv().fromFile(csvFilePath)
.then(jsonObj => {
return res.status(200).json(jsonObj)
})
.catch(e => {
req.error = e
next()
})
},
}
anyone have an idea what might be going on here?
That is simply how .json() works.
It returns promise so you need to handle it asynchronously
var CSVDATA = () => {
fetch('/getnums')
.then(res => res.json())
.then(json => console.log(json));
}
export default {
CSVDATA,
}
MDN link

Why fetch isn't working second time?

This is a very very annoying thing, i'm trying to solve it for hours right now. Here's the code:
//ExpressJS code
app.post('/newname', (req, res) => {
const {name, type, id} = req.body;
console.log(name, type, id)
knex('fl').insert({
name, type, id,
...type === 'category'? {timeValue: req.body.timeValue, timeType: req.body.timeType} : {}
})
.then(() => {
console.log("bar");
return knex('fl').select('*').where('status', 'available')})
.then(data => res.json(data))
.catch(err => console.log(err))
})
//React code
possibleName = (event) => {
this.setState({
possibleName: event.target.value
})
console.log(this.state.possibleName)
}
complete = () => {
if(Boolean(this.state.possibleName)){
console.log(this.state.possibleName)
fetch('http://localhost:3001/newname', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: this.state.possibleName,
type: this.state.type,
id: this.props.id,
...this.state.type === 'category'? {timeValue: this.props.timeValue, timeType: this.props.timeType}:{}
})
})
.then(res => res.json())
.then(data => {
console.log("foo");
this.props.dispatch(getAction(data));
this.setState({
create: 'none',
zindex: 0,
possibleName: ''
})
})
.catch(err => console.log(err))
}
}
//...
//...
<input type='text' value={this.state.possibleName} onChange={this.possibleName}/>
<div onClick={this.complete}></div>
So... The first time the div is clicked, everything works fine. All the logs are in the console. The second time, the complete()'s first log happens, but it seems like the fetch isn't happening. What's the reason? Something blocks the second fetch? If i try it with Postman, with the same format of req.body, everything works fine every time i try it. So i don't know what will be the problem.
Another thing that might the source of the problem i think, is that there's a dispatch. It's possible that redux don't let the fetch to finish? I mean the first fetch begins, but not completes, so if i fetch second time, it get into query, and starts when the fetch before finishes?

Categories

Resources