【发布时间】:2021-03-15 01:45:05
【问题描述】:
我是 Javascript 新手,我正在尝试学习 express 并创建一个应用程序,允许用户创建新食谱、浏览现有食谱和查看食谱。
我通过在 cmd 栏中输入 recipeserver.js 然后在我的 google chrome 上的地址栏中输入 localhost:3000 来运行我的服务器。到目前为止,它加载了 index.html 主页,从那里,我可以单击标题为“创建食谱”的链接,这会将我引导至如下所示的 create.html 页面:
最初,服务器上只有三个配方,它们包含在我在下面包含的 recipeserver.js 代码中的数据库对象中。 create.html 页面允许用户输入配方信息。当点击 Save Recipe 按钮时,addrecipe.js 文件应该使用对资源 /recipes 的 POST 请求将配方数据发送到服务器
在服务器代码中,所有配方都将存储在一个名为数据库的对象中。此对象的键将是唯一的 ID,值将是与这些 ID 关联的配方。我被困在一个任务上,我应该在服务器代码中添加一个路由来处理对 /recipes 资源的 POST 请求。该路由的处理程序应该:
- 提取 POST 请求正文中包含的配方对象
- 为新配方生成一个唯一 ID(等等。一个基本整数,每次添加配方时都会增加。)
- 在食谱对象中添加一个新条目,键是唯一 ID,值是食谱对象。
当通过向我的服务器添加一些食谱来测试我的代码时,我应该能够只记录食谱对象的内容以查看它是否存储了正确的数据,如下图所示(这张图片不是我的):
所以如我屏幕的第一张图片所示,我在create.html中填写了我要添加的食谱的内容。但是,当我单击“保存食谱”按钮时,我没有将食谱的内容加载到我的 cmd 窗口中,而是收到错误消息:
TypeError: C:\Downloads\recipeApplication\views\recipes.pug:8
6| div#main
7| h1 List of Recipes:
> 8| each recipe in recipes
9| a(href="/recipes/" + recipe.id) #{recipe.name}
10| br
11|
Cannot read property 'length' of undefined
对于如何在服务器代码中路由以处理对 /recipes 资源的 POST 请求,我感到有些困惑。我创建了一个名为 loadRecipes() 的函数,我试图在其中完成所有这些工作。我尝试创建一个新的 id 并将其增加 1,就像任务建议的那样。我无法提取 POST 请求正文中包含的配方对象。我尝试了这个并最终将其注释掉,因为它产生了相同的错误。我只是想让“保存食谱”按钮起作用,以便添加的食谱在 cmd 栏中打印其内容,就像在第二张图片中一样,但我真的迷失了并且被大量的信息所淹没我尝试寻找解决方案,希望能帮助我解决这个问题。
这是我所有的代码,以防有人想运行它,但我相信我的问题在于 recipeserver.js 文件。单击“保存食谱”按钮时,addrecipe.js 文件使用对资源 /recipes 的 POST 请求将食谱数据发送到服务器。
recipeserver.js:
const express = require('express');
const fs = require("fs");
const shortId = require("short-id");
const session = require('express-session');
const app = express();
const pug = require("pug");
const port = 3000;
let database = {
"0":{
"ingredients":
[
{"name":"Crab","unit":"Tsp","amount":3},
{"name":"Peas","unit":"Cup","amount":12},
{"name":"Basil","unit":"Tbsp","amount":10},
{"name":"Cumin","unit":"Liter","amount":3},
{"name":"Salt","unit":"Tbsp","amount":1}
],
"name":"Boiled Crab with Peas",
"preptime":"13",
"cooktime":"78",
"description":"A boring recipe using Crab and Peas",
"id":"0"
},
"1":{
"ingredients":
[
{"name":"Peanuts","unit":"Liter","amount":10},
{"name":"Artichoke","unit":"Tsp","amount":3},
{"name":"Basil","unit":"Cup","amount":11},
{"name":"Sage","unit":"Grams","amount":13},
{"name":"Pepper","unit":"Cup","amount":1}
],
"name":"Boiled Peanuts with Artichoke",
"preptime":"73",
"cooktime":"74",
"description":"A exciting recipe using Peanuts and Artichoke",
"id":"1"
},
"2":{
"ingredients":
[
{"name":"Lobster","unit":"Tsp","amount":14},
{"name":"Brussel Sprouts","unit":"Liter","amount":14},
{"name":"Sage","unit":"Tbsp","amount":3},
{"name":"Thyme","unit":"Tbsp","amount":12},
{"name":"Pepper","unit":"Tsp","amount":10},
{"name":"Cumin","unit":"Tbsp","amount":11}
],
"name":"Spicy Lobster with Brussel Sprouts",
"preptime":"86",
"cooktime":"19",
"description":"A tasty recipe using Lobster and Brussel Sprouts",
"id":"2"
}
}
let recipes = {};
for (let recipe in database) {
recipes[recipe.id] = recipe;
};
app.set("view engine", "pug");
app.use(express.static("public"));
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.get("/addrecipe.js", getAddRecipeJS);
app.get("/recipes", loadRecipes);
app.get("/recipe", loadRecipe);
app.route("/recipes", loadRecipes);
app.post("/recipes", loadRecipes);
let id = 1;
function loadRecipes(request, response, next){
response.status(200).render("recipes.pug", {"session": request.session});
/*
console.log("Request received!", request.body);
const newId = shortId.generate();
recipes[newId] = {
id: newId,
type: "recipe",
...request.body,
};
response.sendStatus(201);
*/
id++;
}
function loadRecipe(req, res, next){
res.status(200).render("recipe.pug", {"session": req.session});
}
function getAddRecipeJS(req, res, next){
fs.readFile("addrecipe.js", function(err, data){
if(err){
res.statusCode = 500;
res.end("Error reading file.");
return;
}
res.status(200).send(data);
return;
});
}
app.listen(port);
console.log(`Server listening at http://localhost:${port}`);
index.html:
<html>
<head><title>Recipe App Home Page</title></head>
<body>
<h1>Welcome to the Recipe App</h1>
<br>
<a href="/create.html">Create a Recipe</a><br>
<a href="/recipes">Browse Recipes</a><br>
</body>
</html>
创建.html:
<html>
<head><title>Create a Recipe</title></head>
<body>
<script src="/js/addrecipe.js"></script>
<button type="button" onclick="genRandom()">Generate Random Recipe Data</button>
<button type="button" onclick="submit()">Save Recipe</button>
<br><br>
Recipe Name: <input type="textbox" id="recipename" size="50"><br>
Prep Time: <input type="textbox" id="preptime" size="50"><br>
Cook Time: <input type="textbox" id="cooktime" size="50"><br>
Description: <textarea rows="5" cols="50" id="description"></textarea><br><br>
Add ingredients:<br>
Unit: <select id="unit">
<option value="Tsp">Teaspoon</option>
<option value="Tbsp">Tbsp</option>
<option value="Cup">Cup</option>
<option value="Liter">Liter</option>
<option value="Gram">Gram</option>
</select><br>
Amount: <input type="textbox" id="amount"><br>
Ingredient: <input type="textbox" id="ingredient"><br>
<button type="button" id="add" onclick="addIngredient()">Add Ingredient</button>
<br><br>
<div id="ingredients">
</div><br>
<button type="button" id="submit" onclick="submit()">Save Recipe</button>
</body>
</html>
addrecipe.js:
let descriptors = ["Sweet", "Spicy", "BBQ", "Braised", "Deconstructed", "Broiled", "Boiled", "Flambeed", "Raw", "Smoked", "Butterflied", "Cured", "Grilled", "Poached"];
let proteins = ["Chicken", "Beef", "Lobster", "Shrimp", "Crab", "Turkey", "Duck", "Tofu", "Chickpeas", "Lentils", "Peanuts", "Kangaroo", "Human", "Goose", "Fish", "Pork", "Eggs", "Deer"];
let accompany = ["Broccoli", "Carrots", "Peas", "Potato", "Kale", "Banana", "Artichoke", "Asparagus", "Beans", "Broccoli", "Brussel Sprouts", "Celery", "Melon", "Mushrooms", "Pumpkin"];
let spices = ["Salt", "Pepper", "Basil", "Thyme", "Sage", "Cumin"];
let mealDescriptors = ["tasty", "mediocre", "very good", "boring", "exciting", "delicious", "easy", "ridiculously complex"];
let units = ["Tbsp", "Tsp", "Cup", "Liter", "Grams"]
let recipe = {ingredients: []};
function addIngredient(){
let name = document.getElementById("ingredient").value;
let amount = document.getElementById("amount").value;
let unit = document.getElementById("unit").value;
let ingredient = {name, amount, unit};
recipe.ingredients.push(ingredient);
updateIngredients();
}
function updateIngredients(){
let innerHTML = "";
recipe.ingredients.forEach(ingredient => {
innerHTML += ingredient.amount + " " + ingredient.unit + " " + ingredient.name + "<br>";
});
document.getElementById("ingredients").innerHTML = innerHTML;
}
function submit(){
recipe.name = document.getElementById("recipename").value;
recipe.preptime = document.getElementById("preptime").value;
recipe.cooktime = document.getElementById("cooktime").value;
recipe.description = document.getElementById("description").value;
let req = new XMLHttpRequest();
req.onreadystatechange = function() {
if(this.readyState==4 && this.status==200){
alert("recipe saved");
}
}
//Send a POST request to the server containing the recipe data
req.open("POST", `/recipes`);
req.setRequestHeader("Content-Type", "application/json");
req.send(JSON.stringify(recipe));
}
recipes.pug:
html
head
title Recipes
body
a(href="/create.html") add a recipe
div#main
h1 List of Recipes:
each recipe in recipes
a(href="/recipes/" + recipe.id) #{recipe.name}
br
recipe.pug:
html
head
title #{recipe.name}
body
div#main
h1 #{recipe.name}
br
【问题讨论】:
标签: javascript node.js express http post