fetch不让Express.js/node.js在客户端中从服务器端到EJS模板的响应
目的:从客户端读取输入(数据),将数据发送到服务器端(node.js/express.js),修改服务器端上的数据并发送修改后的数据返回客户端(EJS模板)
问题:当我将fetch()和用于发布的方法设置时,我可以将数据发送到服务器端,但是我无法渲染修改后的数据数据回到客户端。但是,如果我直接将HTML表格与要发布的方法集中使用,则可以实现目标(目的)。但是,我需要发布fetch()。
研究: 为了缩小问题,尤其是检查服务器端代码,我尝试了以下代码,而无需fetch():我将用户的名称从输入中获取并将其发送到服务器端。在服务器端,我添加一个Hello,然后返回“ Hello first_name last_name!”到一个名为Word的EJS变量:
HTML表单(在EJS模板中):
<form action="/users" id="example-form" method="POST">
<label for="first-name">
<strong>First Name:</strong>
<input type="text" name="first_name" id="first-name">
</label>
<label for="last-name">
Last Name:
<input type="text" name="last_name" id="last-name">
</label>
<input type="submit" value="Create new user">
</form>
<br><hr><br>
<% var word %>
<h2><%= word %></h2>
服务器端代码为:
//app.use(express.json())
app.post('/users', (req,res) => {
console.log(req.body)
res.render('index5',
{
word: `Hello ${req.body.first_name} ${req.body.last_name}!`
})
})
我发表了评论
//app.use(express.json())
,并且代码无需它。
现在,我从HTML代码中删除方法=“ post”。以下代码从 Simon Plenderleith的网站:
HTML代码:
<form action="/users" id="example-form">
<label for="first-name">
<strong>First Name:</strong>
<input type="text" name="first_name" id="first-name">
</label>
<label for="last-name">
Last Name:
<input type="text" name="last_name" id="last-name">
</label>
<input type="submit" value="Create new user">
</form>
我将以下内容添加到此HTML代码中,然后将它们全部保存在index5.ejs中:
<br><hr><br>
<% var word %>
<h2><%= word %></h2>
我从 simon plenderleith的网站 index5.ejs:
async function postFormDataAsJson({ url, formData }) {
const plainFormData = Object.fromEntries(formData.entries());
const formDataJsonString = JSON.stringify(plainFormData);
const fetchOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: formDataJsonString,
};
const response = await fetch(url, fetchOptions);
if (!response.ok) {
const errorMessage = await response.text();
throw new Error(errorMessage);
}
return response.json();
}
async function handleFormSubmit(event) {
event.preventDefault();
const form = event.currentTarget;
const url = form.action;
try {
const formData = new FormData(form);
const responseData = await postFormDataAsJson({ url, formData });
console.log({ responseData });
} catch (error) {
console.error(error);
}
}
const exampleForm = document.getElementById("example-form");
exampleForm.addEventListener("submit", handleFormSubmit);
</script>
这给了这一点 :在控制台(客户端Chrome Dev工具)中以下错误消息:
SyntaxError: Unexpected token < in JSON at position 0
另外,在客户端的控制台中,我们看到我们已经收到了一个空对象:
{}
我们仍然看不到任何Hello hello first_name last_name! (例如,约翰·史密斯(John Smith),您好!)在客户端! 该代码也未能将这些字符串归还到
上述服务器代码中的客户端(index5.ejs),我从app.use(express.json())中删除注释//
因此, 服务器端上的代码:
app.use(express.json())
app.post('/users', (req,res) => {
console.log(req.body)
res.render('index5',
{
word: `Hello ${req.body.first_name} ${req.body.last_name}!`
})
})
现在,我们再次尝试约翰·史密斯(John Smith):
这次我们进行了改进,并且在服务器端的控制台中获取了此对象:
{ first_name: 'John', last_name: 'Smith' }
我们看不到Hello John Smith!在客户端上,当我们将fetch()与方法设置的方法使用时,服务器端代码无法将其渲染到EJS变量单词。请记住,当方法=“ post”设置在标签中时,服务器端代码可与HTML表单一起使用。
另外,我仍然在客户端(Chrome dev工具)的控制台中获取此错误消息:
(index):68 SyntaxError: Unexpected token < in JSON at position 0
使用Chrome Dev工具,可以将此错误追溯到上述JavaScript代码中的以下代码行:
console.error(error);
使用Chrome在网络/fetch/xhr/有效载荷下的开发工具,我看到以下内容:
{first_name: "John", last_name: "Smith"}
first_name: "John"
last_name: "Smith"
似乎上面的fetch()代码成功地将数据发送到服务器端,但是服务器端代码的以下部分失败了:
res.render('index5',
{
word: `Hello ${req.body.first_name} ${req.body.last_name}!`
})
清楚,清楚,清楚,我必须更好地了解客户端和服务器端之间的数据如何来回。当我继续为此努力时,如果您可以帮助我找出我所缺少的内容,并且您建议您快速修复上述代码,我将不胜感激。
最好的问候,
ERIC
更新2022年5月4日
如果我
return response.json()
在JavaScript代码(客户端)中更改为
return response
控制台(客户端端)中的错误消息消失。手头的问题:为什么使用常规表格,node.js/express.js可以渲染到EJS模板,但使用fetch()不能。
Purpose: Reading input (data) from the client-side, sending the data to the server-side (Node.js/Express.js), modifying the data on the server-side, and sending the modified data back to the client-side (EJS template)
Problem: When I use fetch() with the method set to POST, I can send data to the server-side, but I cannot render the modified data back to the client-side. However, if I use the HTML form directly with the method set to POST, I can achieve the goal (the purpose). However, I need to POST with fetch().
Research:
To narrow down the problem and especially check on the server-side code, I tried the following code without fetch(): I take the user's name from the input and send it to the server-side. On the server-side, I add a Hello and then return "Hello first_name last_name!" to an EJS variable named word:
The HTML form (in an ejs template):
<form action="/users" id="example-form" method="POST">
<label for="first-name">
<strong>First Name:</strong>
<input type="text" name="first_name" id="first-name">
</label>
<label for="last-name">
Last Name:
<input type="text" name="last_name" id="last-name">
</label>
<input type="submit" value="Create new user">
</form>
<br><hr><br>
<% var word %>
<h2><%= word %></h2>
The server-side code is:
//app.use(express.json())
app.post('/users', (req,res) => {
console.log(req.body)
res.render('index5',
{
word: `Hello ${req.body.first_name} ${req.body.last_name}!`
})
})
I commented out
//app.use(express.json())
and the code works without it.
Now, I remove method = "POST" from the HTML code. The following code is adopted from Simon Plenderleith's website:
HTML code:
<form action="/users" id="example-form">
<label for="first-name">
<strong>First Name:</strong>
<input type="text" name="first_name" id="first-name">
</label>
<label for="last-name">
Last Name:
<input type="text" name="last_name" id="last-name">
</label>
<input type="submit" value="Create new user">
</form>
I add the following to this HTML code and save them all in index5.ejs:
<br><hr><br>
<% var word %>
<h2><%= word %></h2>
I add the following JavaScript code from Simon Plenderleith's website to index5.ejs:
async function postFormDataAsJson({ url, formData }) {
const plainFormData = Object.fromEntries(formData.entries());
const formDataJsonString = JSON.stringify(plainFormData);
const fetchOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: formDataJsonString,
};
const response = await fetch(url, fetchOptions);
if (!response.ok) {
const errorMessage = await response.text();
throw new Error(errorMessage);
}
return response.json();
}
async function handleFormSubmit(event) {
event.preventDefault();
const form = event.currentTarget;
const url = form.action;
try {
const formData = new FormData(form);
const responseData = await postFormDataAsJson({ url, formData });
console.log({ responseData });
} catch (error) {
console.error(error);
}
}
const exampleForm = document.getElementById("example-form");
exampleForm.addEventListener("submit", handleFormSubmit);
</script>
This gives the following error message in the console (client-side Chrome dev tool):
SyntaxError: Unexpected token < in JSON at position 0
Also, in the console in the client-side we see we have received an empty object:
{}
We still do not see any Hello first_name last_name! (e.g. Hello John Smith!) on the client-side! So the code also failed to render back those strings to the client-side (index5.ejs)
In the above-given server code, I remove the comment // from app.use(express.json())
So, this is now the code on the server-side:
app.use(express.json())
app.post('/users', (req,res) => {
console.log(req.body)
res.render('index5',
{
word: `Hello ${req.body.first_name} ${req.body.last_name}!`
})
})
Now, we try John Smith again:
This time we have an improvement and we get this object in the console on the server-side:
{ first_name: 'John', last_name: 'Smith' }
We do not see Hello John Smith! on the client-side, so the server-side code fails to render it to the ejs variable word, when we use fetch() with the method set to POST. Remember, the server-side code worked with HTML form, when method = "POST" was set in the tag.
Also, I still get this error message in the console on the client-side (Chrome dev tool):
(index):68 SyntaxError: Unexpected token < in JSON at position 0
Using the Chrome dev tool, this error can be traced back to the following line of code in the above-given JavaScript code:
console.error(error);
Using Chrome dev tool under Networking/Fetch/XHR/Payload, I see the following:
{first_name: "John", last_name: "Smith"}
first_name: "John"
last_name: "Smith"
Seemingly, the above code with fetch() is successful in sending the data to the server-side but the following part of the server-side code fails:
res.render('index5',
{
word: `Hello ${req.body.first_name} ${req.body.last_name}!`
})
Clearly, I have to find a better understanding of how the data goes back and forth between the client-side and the server-side. While I continue working on this, I appreciate it if you could help me find out what I am missing and if you could suggest a quick fix for the above-given code.
Best regards,
Eric
Update May 4, 2022
If I change
return response.json()
in the JavaScript code (client-side) to
return response
then the error message in the console (client-side) disappears.This, however, does not solve the problem at hand: why with a regular form, node.js/express.js can render to an ejs template but with fetch() it cannot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论