我是学习全栈开发的新手,特别是后端方面的东西,我试图让这个异步的Nodejs得到解决。
我需要在提交忘记密码表单后完成一些后端操作。基本上控制器动作看起来像这样(我知道肯定是以错误的方式):
forgot: function (req, res) {
var token = "febfoebfoui38383303cnc";
var userEmail = req.body.email;
var host = req.headers.host;
AuthService.saveResetPasswordValues(token, userEmail, function (err, savedRecord) {
if (err) { return res.send(404, '\n\nerror occurred\n\n'); }
return res.json(savedRecord);
});
AuthService.sendForgotPasswordEmail(token, userEmail, host, function (err, message) {
if (err) { return res.send(404, '\n\nerror occurred\n\n'); }
return res.json(message);
});
},
每项服务都可以帮助您重置密码重置电子邮件。
saveResetPasswordValues: function (token, userEmail, cb) {
var expiration = Date.now() + 3600000; // 1 hour
User.update({ email: userEmail },
{ resetPasswordToken: token,
resetPasswordExpires: expiration})
.exec(function (err, user) {
if (err) { return cb({ status: 404, message: 'Could not find user with that email address' }); }
return cb(err, user);
});
},
sendForgotPasswordEmail: function (token, userEmail, host, cb) {
var htmlMessage =
'<h4>You are receiving this because you (or someone else) have requested the reset of the password for your account.</h4>' +
'<p>Please click on the following link, or paste this into your browser to complete the process:</p>' +
"<p><a href='http://" + host + '/reset/' + token + "'> Link to password reset </a></p>" +
'<p>If you did not request this, please ignore this email and your password will remain unchanged.</p>';
var emailInfo = {
to: userEmail,
from: "customerservice@smallchangeproj.com",
subject: "Small Change Project Password Reset",
message: htmlMessage,
fromName: "Small Change Project"
};
.... some code for sending the email ...
return cb(null, 'email has been sent');
}
最后,用户应该收到如下所示的电子邮件:
您收到的是因为您(或其他人)要求的 重置您帐户的密码。
请点击以下链接,或将其粘贴到您的浏览器中 完成这个过程:
令人惊讶的是,这段代码确实有效,但是它吐出了一堆丑陋的错误 - 告诉我我不知道异步回调是如何工作的;)
error: Sending 500 ("Server Error") response:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:690:11)
at ServerResponse.res.setHeader (/usr/lib/node_modules/sails/node_modules/express/node_modules/connect/lib/patch.js:133:22)
at ServerResponse.res.set.res.header (/home/zacharyhustles/smallChangeAPI/node_modules/sails/node_modules/express/lib/response.js:577:10)
at ServerResponse.res.send (/home/zacharyhustles/smallChangeAPI/node_modules/sails/node_modules/express/lib/response.js:142:12)
at ServerResponse.res.json (/home/zacharyhustles/smallChangeAPI/node_modules/sails/node_modules/express/lib/response.js:223:15)
at /home/zacharyhustles/smallChangeAPI/api/controllers/UserController.js:123:15
at /home/zacharyhustles/smallChangeAPI/api/services/AuthService.js:50:4
at Object.module.exports.simpleSendEmail (/home/zacharyhustles/smallChangeAPI/api/services/EmailService.js:48:12)
at Object.bound [as simpleSendEmail] (/home/zacharyhustles/smallChangeAPI/node_modules/lodash/dist/lodash.js:729:21)
at Object.module.exports.sendForgotPasswordEmail (/home/zacharyhustles/smallChangeAPI/api/services/AuthService.js:46:16)
at Object.bound [as sendForgotPasswordEmail] (/home/zacharyhustles/smallChangeAPI/node_modules/lodash/dist/lodash.js:729:21)
at Object.module.exports.forgot (/home/zacharyhustles/smallChangeAPI/api/controllers/UserController.js:121:15)
at bound (/home/zacharyhustles/smallChangeAPI/node_modules/lodash/dist/lodash.js:729:21)
at routeTargetFnWrapper (/home/zacharyhustles/smallChangeAPI/node_modules/sails/lib/router/bind.js:179:5)
at callbacks (/home/zacharyhustles/smallChangeAPI/node_modules/sails/node_modules/express/lib/router/index.js:164:37)
at param (/home/zacharyhustles/smallChangeAPI/node_modules/sails/node_modules/express/lib/router/index.js:138:11) [Error: Can't set headers after they are sent.]
这样做的正确方法是什么?我还想将逻辑分成两种服务方法......
答案 0 :(得分:1)
与已经建议的错误消息一样,在您已经发送了一个响应之后,不允许向浏览器发送另一个响应,因为在网页请求的经典请求 - 响应周期中,浏览器每个请求只接受一个响应。
您必须将第二个服务功能的调用放入第一个服务功能的回调中,并将服务助手的结果发送到组合对象中,例如:像这样:
forgot: function (req, res) {
var token = "febfoebfoui38383303cnc";
var userEmail = req.body.email;
var host = req.headers.host;
AuthService.saveResetPasswordValues(token, userEmail, function (err, savedRecord) {
if (err) { return res.send(404, '\n\nerror occurred\n\n'); }
AuthService.sendForgotPasswordEmail(token, userEmail, host, function (err, message) {
if (err) { return res.send(404, '\n\nerror occurred\n\n'); }
// make sure to adapt your client logic for this response
return res.json({savedRecord: savedRecord, message: message);
});
});
},
异步回调的一般结论是,如果你有一个依赖于前一个调用结果的函数调用,你必须将第二个调用始终嵌入到前一个调用的回调中,所以它们会在正确的顺序和第二个调用可以访问第一个的结果。
如果要在一个响应中发送多个异步函数的结果,只需嵌套函数调用,以便在最后最深的回调中访问所有结果。