Node.js结合Mongoose实现Post请求报错问题求助
问题
跟着旧教程构建API时,POST请求失败。使用.post(addNewCoordinates);时出现报错:
Error: Route.post() requires a callback function but got a [object Undefined]
GET请求正常,已尝试添加async/await但问题未解决。MongoDB已通过Compass创建数据库及集合,相关代码如下:
index.js
import express from 'express'; import routes from './src/routes/coordinatesRoutes'; import mongoose from 'mongoose'; import bodyParser from 'body-parser'; const app = express(); routes(app) const PORT = 1234; // Will print at localhost:{Port} app.get('/', (req, res) => res.send(`Node and express server running on port ${PORT}`) ) // Will print in terminal app.listen(PORT, () => console.log(`Your server is running on port ${PORT}`)) // Database Setup // mongoose connection mongoose.Promise = global.Promise; mongoose.connect('mongodb://localhost:27017/coordinates', { useNewUrlParser: true, useUnifiedTopology: true }) //bodyparser setup app.use(bodyParser.urlencoded({ extended: true})); app.use(bodyParser.json()); app.use(function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); next(); });
coordinatesController.js
import mongoose from 'mongoose'; import { InputDataSchema } from '../models/coordinatesModel' const InputData = mongoose.model('InputData', InputDataSchema); const addNewCoordinates = async (req,res) => { let newCoordinates = new InputData(req.body); await newCoordinates.save((err, coordinates) => { if (err) { res.send(err) } res.json(coordinates) }) } export default addNewCoordinates;
coordinatesModel.js
import mongoose from 'mongoose'; const Schema = mongoose.Schema; export const InputDataSchema = new Schema({ latitude: { type: Number, required: "Enter latitude" }, longitude: { type: Number, required: "Enter longitude" }, altitude: { type: Number, required: "Enter altitude" }, ecef: { type: Array }, created_date: { type: Date, default: Date.now } })
coordinatesRoute.js
import addNewCoordinates from '../controllers/coordinatesController' const routes = (app) => { //create route for donations app.route('/lla') //create get request .get((req, res) => res.send('GET request successful!')) //create post request .post((req, res) => res.set('POST request successful!')); // This crashes and gives me a Route.post() requires a callback function but got a [object Undefined] so I'm just trying to focus on getting a post without really any data. //.post(addNewCoordinates); // create a new route so you can get these donation entries by their ID's app.route('/lla/:timestamp') //create put request .put((req, res) => res.send('PUT request successful!')) //create delete request .delete((req, res) => res.send('DELETE request successful')) } export default routes;
解决方案
1. 修复路由链式调用的语法错误
报错的直接原因是路由链式调用被提前终止:在coordinatesRoute.js中,第一个.post()后面的分号会结束整个app.route('/lla')的链式调用,导致后续的.post(addNewCoordinates)失去上下文,无法正确关联到路由对象。
修改coordinatesRoute.js的路由部分,去掉多余的分号,替换为正确的链式调用:
app.route('/lla') // GET 请求 .get((req, res) => res.send('GET request successful!')) // 使用控制器方法处理POST .post(addNewCoordinates);
2. 修正控制器中的异步逻辑问题
你在addNewCoordinates中混用了await和回调函数,mongoose的save()方法如果传入回调就不会返回Promise,await无效,同时错误处理会导致重复发送响应。
修改coordinatesController.js的控制器方法,改用纯async-await写法:
import mongoose from 'mongoose'; import { InputDataSchema } from '../models/coordinatesModel' const InputData = mongoose.model('InputData', InputDataSchema); const addNewCoordinates = async (req, res) => { try { const newCoordinates = new InputData(req.body); const savedCoordinates = await newCoordinates.save(); res.json(savedCoordinates); } catch (err) { res.status(400).send(err); } } export default addNewCoordinates;
3. 调整中间件与路由的加载顺序
在index.js中,你先挂载了路由,再设置body-parser和CORS中间件,导致路由无法解析请求体(POST的参数无法被读取)。
修改index.js的代码顺序,先完成数据库连接、中间件配置,再挂载路由和启动服务:
import express from 'express'; import routes from './src/routes/coordinatesRoutes'; import mongoose from 'mongoose'; import bodyParser from 'body-parser'; const app = express(); const PORT = 1234; // 数据库连接 mongoose.Promise = global.Promise; mongoose.connect('mongodb://localhost:27017/coordinates', { useNewUrlParser: true, useUnifiedTopology: true }); // 中间件配置 app.use(bodyParser.urlencoded({ extended: true})); app.use(bodyParser.json()); // CORS 配置 app.use(function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); next(); }); // 挂载路由 routes(app); // 根路由 app.get('/', (req, res) => res.send(`Node and express server running on port ${PORT}`) ); // 启动服务 app.listen(PORT, () => console.log(`Your server is running on port ${PORT}`) );
4. 修正测试POST的响应写法
原代码中res.set('POST request successful!')是设置响应头,不是发送响应内容,应该使用res.send()或res.json()。
完成以上修改后,POST请求即可正常工作,同时能正确处理数据保存和错误反馈。
内容的提问来源于stack exchange,提问作者Ikura

