我仍然是一个node.js初学者,所以如果我在这里缺少一些基本的知识,请原谅。
因此,我正在使用node.js(express,mongoose,ejs)制作一个注册/登录系统,我想在用户提交登录表单时显示加载的gif,并将用户重定向到“ example.com/密码验证后(bcrypt)。
我当前的login.ejs代码是:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700" rel="stylesheet">
<title>Login</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/styles/login.css">
</head>
<body>
<div class="signup-form">
<form action="/login" class="container-fluid" method="post">
<% if (locals.loading == true) { %>
<div class="form-group">
<img src="/images/spinner.gif" alt="Loading..." class="center-block">
</div>
<% } else { %>
<h2>Login</h2>
<p class="hint-text">Fast and reliable</p>
<div class="form-group">
<input type="email" class="form-control" name="email" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" class="form-control" name="password" placeholder="Password" required aria-autocomplete="list">
</div>
<div class="form-group">
<input type="submit" class="btn btn-success btn-lg btn-block">
</div>
<% } %>
</form>
<div class="text-center">Don't have an account? <a href="/register">Register</a></div>
</div>
</body>
</html>
我的登录控制器是:
const User = require('../models/user')
const bcrypt = require('bcryptjs')
exports.render_view = (req, res) => {
res.render('login', {loading: false})
}
exports.login_user = async (req, res) => {
res.render('login', {loading: true})
const user = {
email: req.body.email,
password: req.body.password
}
const foundUser = await User.findOne({ email: user.email });
if (foundUser) {
bcrypt.compare(user.password, foundUser.password)
.then((result) => {
if (result) res.redirect('/dashboard')
else res.redirect('/login')
})
.catch((err) => {console.log('Exception thrown\n', err)});
} else {
console.log('User not found')
}
}
路线:
const express = require('express')
const router = express.Router()
const login_controller = require('../controllers/login')
router.get('/', login_controller.render_view)
router.post('/', login_controller.login_user)
module.exports = router;
由于某些原因,当我尝试登录时显示错误消息:
Exception thrown
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (.../node_modules/express/lib/response.js:771:10)
at ServerResponse.location (.../node_modules/express/lib/response.js:888:15)
at ServerResponse.redirect (.../node_modules/express/lib/response.js:926:18)
at bcrypt.compare.then (.../controllers/login.js:19:26)
at <anonymous>
由于您没有向我提供更多详细信息,所以我只能根据您发送的信息来猜测问题,希望对您有所帮助。
您报告的错误,即Error: Can't set headers after they are sent.
在尝试两次渲染页面或类似现象时很常见。
[从现在开始我假设您已经注册了用户(即User.findOne({ email: user.email })
将返回某些内容),而您只想登录,这意味着您应该输入if (result) res.redirect('/dashboard')
条件语句。
此外,由于用户可以看到您的表单,我相信您应该有类似的内容:router.get("/login")
,它将为您提供EJS表单给用户,一旦用户提交,就应该转到router.post("/login")
,根据<form action="/login" class="container-fluid" method="post">
,应该是您在问题上提供的控制器,根据我的推理,这意味着您应删除该行 res.render('login', {loading: true})
,并在没有的情况下将其放置在一个router.get
,沿线的东西
router.get ("/login"){
res.render('login', {loading: true})
}
登录EJS templace是您在问题中提供的内容。我不确定这会带来什么好处,因为EJS是静态的,而不是Angular,这意味着很可能您提交后就不会看到旋转的内容。
PS。请经验丰富的人告诉我说对了!我也是初学者!只是想帮助!