【发布时间】:2020-06-27 02:30:34
【问题描述】:
我想提交一个表单,然后从我的 MongoDB 数据库中返回一个对象,而无需重新加载页面。因此,当我提交表单时,我使用了一个事件处理程序来阻止表单的默认行为重新加载页面。问题是这干扰了我的服务器端脚本并导致req.body 返回null。如果我从客户端脚本中删除e.preventDefault(),那么req.body 工作正常,但页面会刷新并仅显示数据库中的 json。我该如何解决这个问题?
这是我的 HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<title>Message in a Bottle</title>
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div id = "icon">
<img id = "iconImg" style = "width:100%"src = "icon.svg"/>
</div>
<div id = "form">
<form method="post" action="/">
<input type="text" name="sender"/>
<textarea rows="20" cols="50" name="message"></textarea>
<button type = "submit" onclick="onClick(event)">submit</button>
</form>
</div>
<div id = "message">
<p id = "senderName"></p>
<p id = "response"></p>
<button onclick="closeMessage()">New Message</button>
</div>
</body>
<script type = "text/javascript" src = "packageHandler.js"></script>
</html>
这是我的客户端脚本:
const form = document.getElementById("form");
const icon = document.getElementById("icon");
const message = document.getElementById("message");
function onClick(e){
e.preventDefault();
console.log("loading results");
form.style.opacity = "0%";
form.style.pointerEvents = "none";
icon.style.width = "80%";
fetch('http://localhost:3000/', {method: 'POST'})
.then((response) => {
icon.style.width = "33%";
message.style.opacity = "100%";
message.style.pointerEvents = "auto";
return response.json();
})
.then((data) => {
document.getElementById("senderName").innerHTML = data.name;
document.getElementById("response").innerHTML = data.message;
});
//await results
//fade in <div id = "message">
//display results in <div id = "message">
}
function closeMessage(){
console.log("message closed")
form.style.opacity = "100%";
form.style.pointerEvents = "auto";
message.style.opacity = "0%";
message.style.pointerEvents = "none";
//fade out <div id = "message">
//fade in <div id = "form"
}
这是我的服务器端脚本:
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
require('dotenv/config');
const app = express();
const fs = require('fs');
const port = 3000;
app.use(express.urlencoded());
app.use(express.static('public'));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
//Routes
app.get('/', (req, res) => {
fs.readFile('./views/home.html', function (err, data) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(data);
res.end();
});
});
app.post('/', (req, res) => {
MongoClient.connect(process.env.DB_CONNECTION, { useUnifiedTopology: true, useNewUrlParser: true }, function (err, db) {
if (err) throw err;
const dbo = db.db("mydb");
const messageTable = dbo.collection("messages");
let myobj =
[{
name: req.body.sender,
message: req.body.message
}];
console.log(myobj)
messageTable.insertMany(myobj, function (err, res) {
if (err) throw err;
console.log("1 document inserted");
});
var myPromise = () => {
return new Promise((resolve, reject) => {
messageTable.aggregate(
[{ $sample: { size: 1 } }]
).toArray((err, data) => {
err
? reject(err)
: resolve(data[0]);
});
});
}
//Step 2: async promise handler
var callMyPromise = async () => {
var result = await (myPromise());
//anything here is executed after result is resolved
return result;
};
//Step 3: make the call
callMyPromise().then(function (result) {
db.close();
res.json(result)
});
});
}); //end mongo client
【问题讨论】:
-
您的
fetch呼叫缺少请求body -
@Phil 你介意详细说明一下吗?
-
@Phil 善待并阅读。当他不使用
event.preventDefault()时它会起作用,所以浏览器可能有一些预定义的行为将 formData 添加到它自己的正文中。 -
@PavelB。它可以在没有
preventDefault()的情况下工作,因为表单提交正常 -
从链接的副本中,忽略已接受的答案并确保阅读其他答案
标签: javascript node.js mongodb express fetch