使用AJAX、Node/Express及MongoDB(Mongoose)提交表单,内容未存储
看起来你遇到的核心问题是表单内容没能正确存入MongoDB,同时服务器的请求处理流程也存在一些小问题,咱们一步步拆解解决:
1. 服务器中间件顺序错误,导致API路由无法生效
你的server.js里,那个没有指定路径的app.use(function (req, res) {...})中间件会拦截所有进来的请求——包括你后续定义的/api/clicks路由。因为Express中间件是按顺序执行的,这个通用中间件在routes(app)之前,导致请求还没到达你的API路由就被处理并返回了,这其实会让clickHandler.addClick根本不会被触发(你说控制台输出了saved!可能是测试时的临时情况,先把这个顺序问题修正)。
修改后的server.js:
var express=require('express') var bodyParser=require("body-parser") var routes=require('./app/routes/index.js') var mongoose=require('mongoose') var app=express() // 先解析请求体 app.use(bodyParser.urlencoded({ extended: false })) // 先挂载API路由 routes(app) // 再处理未匹配到API的请求(比如根路径) app.use(function (req, res) { res.setHeader('Content-Type', 'text/plain') res.write('you posted:\n') res.end(JSON.stringify(req.body, null, 2)) }) mongoose.connect(/* 你的MongoDB连接字符串 */) app.listen(3000)
2. AJAX请求的Content-Type设置错误
你用了FormData却手动设置了Content-Type: application/x-www-form-urlencoded,这会导致bodyParser无法正确解析表单数据。FormData默认应该使用multipart/form-data类型,而且不需要手动设置——浏览器会自动添加包含boundary的正确Content-Type。
修改AJAX脚本,删掉错误的请求头设置:
<script> (function(){ var xhr; var data=document.getElementById('myForm'); data.addEventListener('submit',makeRequest); function makeRequest(e){ e.preventDefault(); var formData=new FormData(data); xhr= new XMLHttpRequest() xhr.onreadystatechange=function(){ if (xhr.readyState === 4 && xhr.status===200) { console.log(xhr.response) } }; xhr.open('POST','/api/clicks',true); // 删掉这行错误的请求头设置 // xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send(formData); } })() </script>
3. 控制器里的参数冲突与字段获取错误
你的addClick方法里,回调函数的参数用了res——这和路由传入的响应对象res重名了,会覆盖掉原本的响应对象。另外,你直接把req.body传给create,但你的Clicks模型定义的是text字段,而表单里的输入框name是message,所以应该取req.body.message。
修改后的clickHandler.server.js:
function clickHandler(){ this.addClick=function(req,res){ // 把回调里的res改成doc,避免和路由的响应对象冲突 Clicks.create({text: req.body.message}, function (err, doc) { if (err) { console.error(err); // 给客户端返回错误响应 return res.status(500).json({error: 'Failed to save content'}); } console.log("saved!") // 给客户端返回成功响应 res.status(200).json({success: true, data: doc}); }) } }
4. 补充:解析multipart/form-data类型请求
默认的bodyParser.urlencoded无法解析multipart/form-data类型的请求体,你需要安装multer中间件来处理:
先安装依赖:
npm install multer
然后在server.js里配置:
var multer = require('multer'); // 用内存存储处理文本表单数据 var upload = multer({ storage: multer.memoryStorage() }); // 在挂载路由前,给/api/clicks添加multer中间件(只处理文本字段) app.use('/api/clicks', upload.none());
验证修改后的流程
- 表单提交时,AJAX发送正确的
multipart/form-data请求 - 服务器先通过multer解析请求体,再到达
/api/clicks路由 addClick正确获取req.body.message,存入MongoDB的text字段- 客户端收到成功响应,控制台能看到返回的文档数据
这样就能让表单文本内容正确存入MongoDB了。
内容的提问来源于stack exchange,提问作者user1881983

