Express.js使用express.Router处理用户注册返回500错误如何解决?
问题根因&修复方案
- 中间件加载顺序错误(最核心问题)
你在app.js中先注册了路由,之后才加载bodyParser中间件,导致post请求提交的表单数据无法被解析,req.body永远是空值,自然无法触发后续逻辑。只需要把bodyParser、fileUpload等请求解析中间件的加载逻辑,移到路由注册之前即可。
- 中间件加载顺序错误(最核心问题)
- 异步逻辑执行顺序错误
db.query和bcrypt.hash都是异步方法,你现在的写法是串行执行,会导致邮箱重复校验、密码校验还没出结果,就已经执行了插入数据库的逻辑,同时bcrypt.hash没有处理异步返回,存入数据库的是Promise对象而非加密后的密码字符串。需要把后续逻辑放到回调内,或者改用async/await写法简化逻辑。
- 异步逻辑执行顺序错误
- 路由注册冗余错误
你已经通过app.use('/', route)把路由挂载到了根路径下,后续的app.use('about', route)等写法不仅冗余,还缺少路径开头的斜杠,可能导致路由匹配异常,直接删掉即可。
- 路由注册冗余错误
修复后的代码
app.js
var express = require('express'); var handlebars = require('express-handlebars').create({ defaultLayout: 'main' }); var dotenv = require('dotenv'); var bodyParser = require('body-parser'); var fileUpload = require('express-fileupload'); var route = require('./routes/auth'); var app = express(); //diable metadata header response app.disable('x-powered-by'); //app template configuration setup app.engine('handlebars', handlebars.engine); app.set('view engine', 'handlebars'); //static resources configuration app.use(express.static(__dirname + '/public')); // 【调整顺序:先加载请求解析中间件】 //file upload config app.use(fileUpload()); app.use(express.static('upload')); //form encoding app.use(bodyParser.urlencoded({ extended: false })); // 【后注册路由,删掉冗余的路由挂载】 app.use('/', route); //app port for viewing app.set('port', process.env.PORT || 3000); //custom 404 page app.use((req, res, next) => { res.status(404); res.render('404'); }); //custom 500 page app.use((err, req, res, next) => { res.status(500); res.render('500'); }); app.listen(app.get('port'), (req, res) => { console.log('Express started on localhost:' + app.get('port') + '; press Ctrl-C to terminate.'); }); module.exports = app;
auth.js(用async/await简化异步逻辑,避免回调地狱)
var express = require('express'); var bcrypt = require('bcrypt'); var fortune = require('../lib/fortune'); var db = require('../controllers/database'); var router = express.Router(); // 把db.query封装成promise形式方便用await,如果你用的是mysql2模块本身就支持promise写法可以跳过这步 const util = require('util'); db.query = util.promisify(db.query); // define the home page route router.get('/', (req, res) => { res.render('home'); }); //About Page route router.get('/about', (req, res) => { res.render('about', { fortune: fortune.getFortune }); }); //middleware registration page route router.get('/register', (req, res) => { res.render('register'); }); // 加async关键字 router.post('/register', async (req, res) => { try { var { firstName, lastName, email, password, passwordConfirm } = req.body; // 等待查询结果返回 const results = await db.query('SELECT email FROM registration WHERE email = ?', [email]); if (results.length > 0) { return res.render('register', { message: 'That email is already in use' }) } else if (password !== passwordConfirm) { return res.render('register', { message: 'Passwords do not match' }) } // 等待密码加密完成 let hashedPwd = await bcrypt.hash(password, 10); console.log(hashedPwd); // 等待插入完成 await db.query('INSERT INTO registration SET ? ', { firstName: firstName, lastName: lastName, email: email, password: hashedPwd }); return res.render('register', { message: 'User registered' }); } catch (error) { console.log(error); return res.status(500).render('register', { message: '系统异常,请稍后重试' }) } }); router.get('/login', (req, res) => { res.render('login'); }); module.exports = router;
内容的提问来源于stack exchange,提问作者GiddyGiddy
相关产品推荐
相关产品推荐

