TypeError: req.body.forEach is not a function 问题:选中食物营养成分总和计算功能报错排查
Hey there! Let's break down what's causing that error and fix your nutrition calculation feature step by step.
First, why you're getting TypeError: req.body.forEach is not a function
req.body is an object (not an array) containing the key-value pairs from your form submission. You can't use forEach on an object directly—that's the root of your error. On top of that, your current form naming and SQL query structure have a few issues that are keeping the feature from working as intended.
Let's fix this step by step
1. Update your frontend EJS template
Right now, your quantity inputs have names like qty 0, qty 1, which makes it impossible to link them to specific food items. Let's rename them to tie directly to the food's name, so we can easily match quantities to selected foods:
<% availableFood.forEach(function(food_item){ %> <tr> <td> <input type="checkbox" name="selectedFood[]" value="<%= food_item.name %>" /> </td> <td> <input type="text" name="qty[<%= food_item.name %>]" value="1" style="width: 30px" /> </td> <td><%= food_item.name %></td> <td><%= food_item.typical_values %></td> <td><%= food_item.unit_of_the_typical_value %></td> <td><%= food_item.calories %></td> <td><%= food_item.carbs %></td> <td><%= food_item.fat %></td> <td><%= food_item.protein %></td> <td><%= food_item.salt %></td> <td><%= food_item.sugar %></td> </tr> <% }) %>
Now qty will be an object in req.body where keys are food names, and values are their quantities. selectedFood[] will come through as an array of chosen food names.
2. Rewrite your Express route (simpler, more reliable version)
Instead of trying to do all the calculation in SQL, let's fetch the selected food data first, then compute totals in code. This is easier to read and debug:
app.post("/calculate", function (req, res) { const selectedFoods = req.body.selectedFood; const quantities = req.body.qty; // Object: { "Apple": "2", "Banana": "1", ... } // Handle edge case: no foods selected if (!selectedFoods || selectedFoods.length === 0) { return res.send("Please select at least one food item to calculate."); } // Fetch all selected food items from the database const sqlquery = "SELECT name, calories, carbs, fat, protein, salt, sugar FROM food_item WHERE name IN (?)"; db.query(sqlquery, [selectedFoods], (err, foodResults) => { if (err) { console.error(err.message); return res.status(500).send("Error fetching food data."); } // Calculate total nutrition values const totalNutrition = { calories: 0, carbs: 0, fat: 0, protein: 0, salt: 0, sugar: 0 }; foodResults.forEach(food => { // Parse quantity (default to 1 if input is invalid) const qty = parseInt(quantities[food.name]) || 1; // Multiply each nutrient by quantity and add to total totalNutrition.calories += food.calories * qty; totalNutrition.carbs += food.carbs * qty; totalNutrition.fat += food.fat * qty; totalNutrition.protein += food.protein * qty; totalNutrition.salt += food.salt * qty; totalNutrition.sugar += food.sugar * qty; }); res.send(` The total nutritional information for ${selectedFoods.join(', ')} is:<br> ${JSON.stringify(totalNutrition, null, 2)} `); }); });
What we fixed:
- No more
req.body.forEacherror: we're working with theselectedFoodsarray from your form instead of the entirereq.bodyobject. - Linked quantities to specific foods using named input keys, so we can accurately multiply each food's nutrients by its quantity.
- Added edge case handling for when no foods are selected.
- Made the code easier to read and debug by splitting the database fetch and calculation steps.
内容的提问来源于stack exchange,提问作者ahmadalibin

