错误:发送后无法设置标题,仅在刷新页面后发生

Posted

技术标签:

【中文标题】错误:发送后无法设置标题,仅在刷新页面后发生【英文标题】:Error: Can't set headers after they are sent , happen only after refreshing a page 【发布时间】:2015-03-24 19:18:26 【问题描述】:

每次我在路由 'localhost:8080/' 刷新 html 页面或登录用户时,我都会收到此 错误:发送后无法设置标题。 据我所知发生此问题是由于意外调用了两次回调。该应用程序不会崩溃或发生任何事情,它只是在控制台上不断记录相同的错误。

这是代码。

var User        = require('../models/user');
var Story       = require('../models/story');
var jwt         = require('jsonwebtoken');
var config      = require('../../config');


var superSecret = config.secret;


module.exports = function(app, express) 

    // creating our first router
    var apiRouter = express.Router();

    // signup a user

    apiRouter.post('/signup', function(req, res) 

            var user = new User(
                name: req.body.name,
                username: req.body.username,
                password: req.body.password
            );

            user.save(function(err) 
                if(err) res.send(err);
                res.json( message: 'User has been created!' );
            );
    );

    apiRouter.get('/users', function(req, res) 

        User.find(, function(err, users) 

            if(err) res.send(err);

            res.json(users);

        );

    );



    // user login

    apiRouter.post('/login', function(req, res) 

        User.findOne(
            username: req.body.username
        ).select('name username password').exec(function(err, user) 

            if(err) throw err;

            if(!user) 
                res.json( message: "Wrong User" );
             else if(user) 

                var validPassword = user.comparePassword(req.body.password);

                if(!validPassword) 
                    res.json( message: "Invalid Password" );

                 else 

                    var token = jwt.sign(
                        id: user._id,
                        name: user.name,
                        username: user.username
                    , superSecret, 
                        expiresInMinute: 1440
                    );

                    // return all the sucess
                    res.json(
                        success: true,
                        message: "Successfully login and token created!" + token.name,
                        token: token

                    );
                ;

            

        );

    );


    // write a middleware for login
    // A middleware for login user only, once a user has logged in , he can enter other links below
    apiRouter.use(function(req, res, next) 

        // do logging
        console.log("Somebody just came to our app!");

        var token = req.body.token || req.param('token') || req.headers['x-access-token'];

        // check if token exist
        if(token) 

            jwt.verify(token, superSecret, function(err, decoded) 
                if(err) 
                    res.status(403).send( success: false, message: 'Failed to authenticate user' );
                 else 

                    // if everything is good save request for use in other routes
                    req.decoded = decoded;

                    next(); 
                
            );

         else 
            res.status(403).send( success: false, message: 'No token provided' );
        
    );


    apiRouter.route('/')

        .post(function(req, res) 

            var story = new Story(
                user: req.decoded.id,
                content: req.body.content
            );

            story.save(function(err, stor) 
                if(err) res.send(err)
                console.log(stor);
                res.json(stor);
            );

        )


        .get(function(req, res) 

            Story.find( user: req.decoded.id , function(err, story) 
                if(err) res.send(err);

                res.json(story);
            );


        );




    apiRouter.get('/me', function(req, res) 

        res.send(req.decoded.name);

    );

    apiRouter.route('/:user_id')


        .get(function(req, res) 

            User.findById(req.params.user_id, function(err, user) 
                if(err) res.send(err);

                res.json(user);

            );


        )

        .put(function(req, res) 

            User.findById(req.params.user_id, function(err, user) 

                if(err) res.send(err);

                if(req.body.name) 
                    user.name = req.body.name;
                

                if(req.body.username) 
                    user.username = req.body.username;

                

                if(req.body.password) 
                    user.password = req.body.password;
                

                user.save(function(err) 
                    if(err) res.send(err);

                    res.json( message: "User updated" );

                );


            );

        );

    return apiRouter;


【问题讨论】:

【参考方案1】:

发生错误时,您发送了两次响应:

if (err) res.send(err);
res.json(foo);

替换为:

if (err)  res.send(err); return; 
res.json(foo);

【讨论】:

谢谢你的回答,但我不太明白为什么它会调用两次?因为 if err then send if not res.json? 因为大部分代码基本都是这样写的,需要把逻辑相同的代码全部改掉吗? 遗憾的是,这是回调地狱的最新技术。学会爱样板,包括if (err) done(err); return;

以上是关于错误:发送后无法设置标题,仅在刷新页面后发生的主要内容,如果未能解决你的问题,请参考以下文章

CSS样式有时仅在jsf页面上的页面刷新后应用?

刷新网格后剑道ui网格可分页大小发生变化

jQuery Mobile 弹出页面导航后不显示,仅在硬刷新或返回同一页面后显示

将标头发送到客户端后无法设置标头/服务器在页面刷新时崩溃

令牌输入仅在我刷新页面后才有效

新记录保存在存储中,但仅在刷新页面后显示