I am retrieving a JSON object from an external database using a private api key. I am using express as my HTTP. I am building a nutrition app that gathers a list of foods given by an input from the UI. When more than one food object is returned, the error occurs that I cannot set headers after they are sent to the client. My goal is to have a drop down of list of foods when a user types in a food. Mustache edge up.
I've tried limiting only one food object output; no error occurs. I've tried setting the food objects into separate object arrays and the error still persists. I've made sure to use return to catch only one response if previous results were to occur to prevent other express routing from executing. Not sure where the add image button here is, but here is an example of what outputs in fetchFoods.js:
{ foodName: 'ARMADILLO EGGS, UPC: 732170002859', foodNum: '45220998' } { foodName: 'ARMADILLO EGGS, UPC: 732170003856', foodNum: '45201506' } { foodName: 'ARTESANIA, TOASTED ALMOND EGG NOUGHT, UPC: 815961010209', foodNum: '45161494' }...
However, when executing from index.js, that's where the error occurs. When referring to errors I've mentioned, that's only when is executed at index.js. Otherwise, I am able to output multiple food objects from the database directly from the file.
_http_outgoing.js:482 throw new ERR_HTTP_HEADERS_SENT('set'); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:482:11)
In terms of limiting one food result, no error occurs from either executing from or index.js. I think my problem lies within my express configuration. I'm able to view the food result (only if limited to one) in my terminal and my console but not if there more than one.
Cool shaving style
This is the original JSON object:
list": { "q": "eggs", "sr": "1", "ds": "any", "start": 0, "end": 25, "total": 1956, "group": "", "sort": "n", "item": [ { "offset": 0, "group": "Branded Food Products Database", "name": "AHOLD, DEVILED EGG POTATO SALAD, UPC: 688267141584", "ndbno": "45044170", "ds": "LI", "manu": "Ahold USA, Inc." },
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="icon" href="/img/app_logo.png"/> <link rel="stylesheet" href="/css/styles.css"> <title>Profile</title> </head> <body> <div class="main-content"> {{>header}} <p>{{title}}</p> <p>{{greeting}}</p> <form> <input placeholder="Search for foods"> <button>Search</button> </form> </div> {{>footer}} <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.1/mustache.min.js"></script> <script src="/js/app.js"></script> </body> </html>
app.get('/fetchFoods', (req, res, next) => { if (!req.query.food){ return res.send({ error: 'You must provide a food!' }); } next(); fetchFoods(req.query.food, (error, {foodName, foodNum} = {}) => { if (error) { return res.send({error}); } else { return res.send({ foodName, foodNum }); } }); });
const foodForm = document.querySelector('form'); const search = document.querySelector('input'); foodForm.addEventListener('submit', (e) => { console.log('testing'); e.preventDefault(); const food = search.value; fetch('http://localhost:3000/fetchFoods?food=' + food).then((response) => { response.json().then((data) => { if (data.error) { console.log(data.error); } else { console.log(data.foodName); console.log(data.foodNum); } }).catch(err => { console.log("Error Reading data " + err); }); }); }); app.listen(port, () => console.log(`Listening on port ${port}`));
const request = require('request'); const fetchFoods = (food, callback) => { const url = 'https://api.nal.usda.gov/ndb/search/?format=json&q=' + encodeURIComponent(food) + '&sort=n&max=25&offset=0&api_key=###'; request({url:url, json:true}, (error, {body}) => { if (error) { callback('Unable to connect to USDA database!', undefined); } else if (body.errors) { callback(body.errors.error[0].message); } var foodItem = body.list.item; for (var i = 0; i < foodItem.length; i++){ callback(undefined, { foodName: foodItem[i].name, foodNum: foodItem[i].ndbno }); } }); }; fetchFoods('eggs', (error, data) => { if (error) { return console.log(error); } else { return console.log(data); } }); module.exports = fetchFoods;
{ "name": "nutrition-app-heroku", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "start": "nodemon -e js,hbs", "dev": "nodemon -e js,hbs" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1", "hbs": "^4.0.4", "mongodb": "^3.2.7", "mongoose": "^5.6.4", "mustache": "^3.0.1", "request": "^2.88.0", "validator": "^11.1.0" }, "devDependencies": { "nodemon": "^1.19.1" } }
The error means that you are calling multiple timesm, you can only send once.
for (var i = 0; i < foodItem.length; i++){ callback(undefined, { foodName: foodItem[i].name, foodNum: foodItem[i].ndbno }); }
You should send back the object:
Cowboy mustache styles
callback(undefined, foodItem);
Then send the foodItems to the client:
fetchFoods(req.query.food, (error, foodItems) => { if (error) { return res.send({error}); } else { res.send(foodItems); } });
Comments
There are no comments for this post "javascript - Retrieving multiple JSON objects from a database results in Express error - Stack Overflow". Be the first to comment...
Add Comment