【问题标题】:Can't set headers after they are sent node发送节点后无法设置标头
【发布时间】:2018-07-05 20:04:06
【问题描述】:

密码重置表单我有以下路线,表单有密码和密码确认字段。

router.post('/users/reset/:token', (req, res, next) => {
  if(req.body.password === req.body['password-confirm']) {
    req.flash('error', 'Passwords do not match!');
    res.redirect('/users/forgot');
  }

  User.findOne({
    resetPasswordToken: req.params.token,
    resetPasswordExpires: { $gt: Date.now() }
  }, function(err, user) {
    if(!user) {
      req.flash('error', ' Password reset is invalid or has expired');
      res.redirect(302, '/login');
    }

    const setPassword = promisify(user.setPassword, user);
    setPassword(req.body.password);
    user.resetPasswordToken = undefined;
    user.resetPasswordExpires = undefined;
    const updatedUser = user.save();

    user.save((saveError, updatedUser) => {
      // Check if saveError is present here and handle appropriately
      req.login(updatedUser, loginError => {
        req.flash('success_msg', 'Your password has been reset successfully! You are now logged in!');
        res.redirect('/dashboard' + req.user);
      })
    });
  });
});

填写表格时出现以下错误

Fri Jan 26 2018 11:28:55 GMT+0000 (GMT): GET /users/reset/6e2574bfa532e0d13af7fae61114308f9a683767
Mongoose: users.findOne({ resetPasswordExpires: { '$gt': new Date("Fri, 26 Jan 2018 11:28:55 GMT") }, resetPasswordToken: '6e2574bfa532e0d13af7fae61114308f

9a683767' }, { fields: {} })
Fri Jan 26 2018 11:28:55 GMT+0000 (GMT): GET /favicon.ico
Fri Jan 26 2018 11:29:02 GMT+0000 (GMT): POST /users/reset/6e2574bfa532e0d13af7fae61114308f9a683767
Mongoose: users.findOne({ resetPasswordExpires: { '$gt': new Date("Fri, 26 Jan 2018 11:29:02 GMT") }, resetPasswordToken: '6e2574bfa532e0d13af7fae61114308f
9a683767' }, { fields: {} })
Mongoose: users.update({ _id: ObjectId("5a5c6740b9e210087e098fd6") }, { '$unset': { resetPasswordExpires: 1, resetPasswordToken: 1 } })
Mongoose: users.update({ _id: ObjectId("5a5c6740b9e210087e098fd6") }, { '$unset': { resetPasswordExpires: 1, resetPasswordToken: 1 } })
(node:1451) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'apply' of undefined
    at /Users/benbagley/Code/poetry-out-loud/node_modules/es6-promisify/dist/promisify.js:75:41
    at new Promise (<anonymous>)
    at /Users/benbagley/Code/poetry-out-loud/node_modules/es6-promisify/dist/promisify.js:54:20
    at /Users/benbagley/Code/poetry-out-loud/routes/users.js:321:5
    at model.Query.<anonymous> (/Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/model.js:4056:16)
    at /Users/benbagley/Code/poetry-out-loud/node_modules/kareem/index.js:273:21
    at /Users/benbagley/Code/poetry-out-loud/node_modules/kareem/index.js:131:16
    at process._tickCallback (internal/process/next_tick.js:150:11)
(node:1451) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a c
atch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:1451) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminat
e the Node.js process with a non-zero exit code.
Fri Jan 26 2018 11:29:02 GMT+0000 (GMT): GET /users/forgot
events.js:136
      throw er; // Unhandled 'error' event
      ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at validateHeader (_http_outgoing.js:503:11)
    at ServerResponse.setHeader (_http_outgoing.js:510:3)
    at ServerResponse.header (/Users/benbagley/Code/poetry-out-loud/node_modules/express/lib/response.js:767:10)
    at ServerResponse.location (/Users/benbagley/Code/poetry-out-loud/node_modules/express/lib/response.js:884:15)
    at ServerResponse.redirect (/Users/benbagley/Code/poetry-out-loud/node_modules/express/lib/response.js:922:18)
    at req.login.loginError (/Users/benbagley/Code/poetry-out-loud/routes/users.js:332:13)
    at /Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/http/request.js:51:48
    at /Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/sessionmanager.js:16:14
    at pass (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/authenticator.js:297:14)
    at Authenticator.serializeUser (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/authenticator.js:299:5)
    at SessionManager.logIn (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/sessionmanager.js:14:8)
    at IncomingMessage.req.login.req.logIn (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/http/request.js:50:33)
    at user.save (/Users/benbagley/Code/poetry-out-loud/routes/users.js:330:11)
    at /Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/model.js:4056:16
    at /Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/services/model/applyHooks.js:170:20
    at process._tickCallback (internal/process/next_tick.js:150:11)

我还是 node 新手,因此任何重构技巧或对此的修复将不胜感激,在这个问题上停留了几天,不知道我做错了什么。

谢谢。

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    第一件事是当节点多次发送API调用响应时会发生此错误。其次,发送响应时最好使用return,例如return res.json(&lt;OBJECT&gt;);

    在您的代码中,您正在检查密码,例如 req.body.password === req.body['password-confirm'] 它应该像 req.body.password !== req.body['password-confirm'] 这可能是导致节点发送多个响应的情况

    【讨论】:

      【解决方案2】:

      您多次向客户端发送响应,这就是面临Cannot set headers after they are sent to the client 错误的原因。

      在你的情况下,你不是returning(退出)你应该有的函数执行。例如。当密码不匹配时,您正在尝试将用户重定向到/users/forgot,但您没有在那里返回该函数。因此,if 条件下的代码将执行并尝试再次发送响应。

      解决方案

      router.post('/users/reset/:token', (req, res, next) => {
          if // some condition {
            // some code
            return res.redirect('/users/forgot');
          }
      
          User.findOne({
             // some code
          }, function(err, user) {
             if(!user) {
                  // some code
                 return res.redirect(302, '/login');
             }
      
             // some code 
             user.save((saveError, updatedUser) => {
                 req.login(updatedUser, loginError => {
                     // some code
                     return res.redirect('/dashboard' + req.user);
                 })
             });
          });
      });
      

      【讨论】:

      • 我在上面试过你的解决方案,这里是我的code now 我也在代码下面输出了错误。感谢您到目前为止的帮助^_^
      • 我在要点上发表了评论
      • 再次更新了要点
      猜你喜欢
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多