Nodejs /reg注册页面部门代码重复执行问题(node-开发指南中)

Nodejs /reg注册页面部门代码重复执行问题(node-开发指南中)

按照nodejs开发指南中的代码,发布微博等功能已经开发完成,回头运行注册等页面,其中127.0.0.1:8000/reg(post)页面中部分代码会重复执行,并且服务器报错。

报错信息如下: events.js:72 throw er; // Unhandled ‘error’ event ^ Error: Can’t set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (http.js:692:11) at ServerResponse.res.setHeader (/home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/express/node_modules/connect/lib/patch.js:59:22) at ServerResponse.res.set.res.header (/home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/express/lib/response.js:527:10) at ServerResponse.res.location (/home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/express/lib/response.js:661:8) at ServerResponse.res.redirect (/home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/express/lib/response.js:703:8) at /home/cplatform/node/node-0.10.19/webapp/microblog/routes/index.js:84:5 at /home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/user.js:31:3 at /home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/mongodb/lib/mongodb/collection.js:347:9 at Server.Base._callHandler (/home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/mongodb/lib/mongodb/connection/base.js:382:41) at /home/cplatform/node/node-0.10.19/webapp/microblog/node_modules/mongodb/lib/mongodb/connection/server.js:472:18

/routes/index.js 中/reg代码如下: app.post(’/reg’, checkNotLogin); app.post(’/reg’,function(req,res){ if(req.body[‘password-repeat’] != req.body[‘password’]){ req.flash(‘error’,‘两次输入的口令不一致’); return res.redirect(’/reg’); } var md5 =crypto.createHash(‘md5’); var password = md5.update(req.body.password).digest(‘base64’);

var newUser = new User({ name: req.body.username, password:password, }); User.get(newUser.name, function(err, user){ if(user) err = ‘Username already exists.’; if(err){ req.flash(‘error’, err); return res.redirect(’/reg’); } newUser.save(function(err){ if(err){ req.flash(‘error’, err); return res.redirect(’/reg’); } console.log(‘jjjjjjjjjjjj’); req.session.user = newUser; console.log(req.session.user); req.flash(‘success’, ‘reg success’) res.redirect(’/’); }); }); });

其中运行两次的部分为: jjjjjjjjjjjj { name: ‘rr’, password: ‘UU8bQ59AT4b3cJD6ntyWzg==’ } POST /reg 302 16ms - 68b jjjjjjjjjjjj { name: ‘rr’, password: ‘UU8bQ59AT4b3cJD6ntyWzg==’ }

百思不得其姐,求各位大神指点迷津


7 回复

Node.js /reg 注册页面代码重复执行问题

问题描述

在实现一个基于 Node.js 的微博应用时,根据开发指南中的代码,发布微博等功能已经开发完成。但在运行注册页面时(127.0.0.1:8000/reg),发现部分代码会重复执行,并且服务器报错。

报错信息

events.js:72
throw er; // Unhandled ‘error’ event
^
Error: Can’t set headers after they are sent.

问题分析

错误信息表明 Can't set headers after they are sent,这通常是因为响应已经被发送后尝试再次设置响应头或发送响应。从代码来看,问题可能出在 res.redirect('/reg') 被多次调用。

示例代码

以下是 /routes/index.js 文件中的 /reg 路由代码:

const express = require('express');
const app = express();
const crypto = require('crypto');
const User = require('./models/User'); // 假设 User 模型在这里定义
const flash = require('connect-flash');

// 中间件检查是否已登录
function checkNotLogin(req, res, next) {
    if (req.session.user) {
        return res.redirect('/');
    }
    next();
}

app.use(flash());

app.post('/reg', checkNotLogin);

app.post('/reg', function(req, res) {
    if (req.body['password-repeat'] !== req.body['password']) {
        req.flash('error', '两次输入的口令不一致');
        return res.redirect('/reg');
    }

    const md5 = crypto.createHash('md5');
    const password = md5.update(req.body.password).digest('base64');

    const newUser = new User({
        name: req.body.username,
        password: password,
    });

    User.get(newUser.name, function(err, user) {
        if (user) {
            err = 'Username already exists.';
        }
        if (err) {
            req.flash('error', err);
            return res.redirect('/reg');
        }

        newUser.save(function(err) {
            if (err) {
                req.flash('error', err);
                return res.redirect('/reg');
            }

            console.log('jjjjjjjjjjjj');
            req.session.user = newUser;
            console.log(req.session.user);
            req.flash('success', '注册成功');
            res.redirect('/');
        });
    });
});

module.exports = app;

解决方案

  1. 确保中间件顺序正确:将 checkNotLogin 中间件放在路由处理函数之前。
  2. 避免多次重定向:确保在每次响应发送后不再调用 res.redirect 或其他设置响应的方法。

总结

通过调整中间件顺序和确保响应只发送一次,可以解决 Can't set headers after they are sent 的问题。上述代码展示了如何正确处理用户注册逻辑并避免重复执行问题。


用 node 0.6 + express 1.x 试试看,版本问题。

有可能。。书里的代码都是老版本的样式。。

但是路由指向,代码都应该是正确的。怎么会执行两次,奇怪。。

顶。。。

貌似在学习这个N-blog的第一章的时候,都有这个问题

根据你提供的错误信息和代码片段,问题在于路由处理函数被多次调用,导致响应头多次设置。具体来说,在 /reg 路由处理中,checkNotLogin 函数被两次注册到同一个路由上,这会导致中间件和实际处理逻辑都被执行两次。

示例代码修正

首先,确保路由只注册一次:

app.post('/reg', checkNotLogin, function(req, res) {
    if (req.body['password-repeat'] !== req.body['password']) {
        req.flash('error', '两次输入的口令不一致');
        return res.redirect('/reg');
    }

    var md5 = crypto.createHash('md5');
    var password = md5.update(req.body.password).digest('base64');

    var newUser = new User({
        name: req.body.username,
        password: password,
    });

    User.get(newUser.name, function(err, user) {
        if (user) {
            err = 'Username already exists.';
        }
        if (err) {
            req.flash('error', err);
            return res.redirect('/reg');
        }
        newUser.save(function(err) {
            if (err) {
                req.flash('error', err);
                return res.redirect('/reg');
            }
            console.log('jjjjjjjjjjjj');
            req.session.user = newUser;
            console.log(req.session.user);
            req.flash('success', 'reg success');
            res.redirect('/');
        });
    });
});

详细解释

  1. 路由注册:确保 app.post('/reg', checkNotLogin) 只注册一次。在你的代码中,checkNotLogin 被注册了两次,导致中间件和实际处理逻辑被多次执行。

  2. 错误处理:每次响应之前检查是否有错误,如果有错误则返回重定向并结束请求处理流程。

  3. 密码哈希:使用 crypto.createHash 对密码进行哈希处理,并存储其 base64 编码形式。

  4. 用户查找与保存:查找数据库中是否存在相同用户名的用户,如果存在则返回错误信息;否则保存新用户并设置会话信息。

通过以上修改,可以避免重复执行问题,并解决 Can’t set headers after they are sent 错误。

回到顶部