javascript - 从数据库检索多个 JSON 对象会导致 Express 错误

标签 javascript node.js express request handlebars.js

我正在使用私有(private) api key 从外部数据库检索 JSON 对象。我使用express作为我的HTTP。我正在构建一个营养应用程序,它收集用户界面输入给出的食物列表。当返回多个食物对象时,会出现错误,即在将它们发送到客户端后我无法设置 header 。我的目标是当用户输入食物时有一个食物列表的下拉列表。

我尝试只限制一种食物对象的输出;没有错误发生。我尝试将食物对象设置为单独的对象数组,但错误仍然存​​在。如果发生先前的结果,我已确保使用 return 仅捕获一个响应,以防止执行其他快速路由。不确定这里的添加图像按钮在哪里,但这里是 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' }
...

但是,当从index.js执行时,就会出现错误。当提到我提到的错误时,只有在index.js 执行fetchFoods.js 时才会出现这种情况。否则,我可以直接从 fetchFoods.js 文件从数据库输出多个食物对象。

_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)

就限制一种食物结果而言,从 fetchFoods.js 或 index.js 执行都不会发生错误。我认为我的问题出在我的快速配置上。我可以在我的终端和控制台中查看食物结果(仅当仅限于一个时),但如果有多个则无法查看。

编辑

这是原始的 JSON 对象:

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."
},

配置文件.hbs

<!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>

index.js

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
            });
        }
    }); 
});

app.js

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}`));

fetchFoods.js

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;

package.json

{
  "name": "nutrition-app-heroku",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "nodemon src/index.js -e js,hbs",
    "dev": "nodemon src/index.js -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"
  }
}

最佳答案

该错误表示您多次调用 res.send,只能发送一次。

我认为错误在这里:

for (var i = 0; i < foodItem.length; i++){          
    callback(undefined, {
             foodName: foodItem[i].name,
             foodNum: foodItem[i].ndbno
    });  
} 

您应该发回该对象:

callback(undefined, foodItem);

然后将 foodItems 发送给客户端:

fetchFoods(req.query.food, (error, foodItems) => {
        if (error) {
            return res.send({error});
        } else {
            res.send(foodItems);
        }
    }); 

关于javascript - 从数据库检索多个 JSON 对象会导致 Express 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57435676/

相关文章:

javascript - 如果值为空,则验证不起作用

javascript - Sbt 0.13 ScriptEngine 对于 getEngineByName 为 Null (“JavaScript” )

php - 将加密/解密函数从 PHP 转换为 NodeJS

javascript - NodeJS - 对象的对象未定义?

node.js - 我将如何测试在 express 中使用 mocha/chai/superagent 发送路由?

javascript - 如何让node js express服务器并行处理请求

javascript - 快速发送新的 HTML 页面,无需重定向

javascript - 我正在进行在线测试,一切都完成了。但我的自动提交计时器不起作用。

javascript - 获取工作表的范围,直到包含数据的最后一个单元格

javascript - 无法从其对象实例访问类函数