Подтвердить что ты не робот

Express.js Ошибка маршрутизации: не удается установить заголовки после их отправки

Я не уверен, почему я получаю эту ошибку. Это простой API, построенный на express.js, чтобы иметь возможность добавлять и удалять сообщения. Ошибка возникает, когда я запускаю маршрутизатор удаления. Я читал, что ошибка обычно возникает, когда есть два обратных вызова, однако я, похоже, не могу найти двойные обратные вызовы.

    _http_outgoing.js:344
    throw new Error('Can\'t set headers after they are sent.');
    Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
    at ServerResponse.header (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:718:10)
at ServerResponse.send (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:163:12)
    at ServerResponse.json (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:249:15)
    at /Users/bounty/Projects/_learning/react-express/server/routes/posts.js:86:9
    at nextTickCallbackWith0Args (node.js:452:9)
    at process._tickCallback (node.js:381:13)

Вот мой маршрутизатор posts.js:

module.exports = function(router) {

    var Post = require('../models/post.js');

    // middleware for the api requests
    router.use(function(req, res, next) {
        // do logging
        console.log('something is happening.');
        next(); // make sure we go to our next route and don't stop here
    });

    // test route to make sure everything is working (accessed at GET http://localhost:8080/api)

    router.get('/', function(req, res) {
        res.json({ message: 'hooray! welcome to our api!' });   
    });

    // all routes here

    // routes that end in /posts
    router.route('/posts')

        // create a Post (accessed at POST http://localhost:7777/api/posts)
        .post(function(req, res) {
            var post = new Post();
            post.postTitle = req.body.postTitle; // set the post name (comes from request) 

            // save post and check for errors
            post.save(function(err) {
                if (err)
                    res.send();

                res.json({ message: 'post created!' });
            });
        })

        // get all Posts (accessed at GET http://localhost:7777/api/posts)
        .get(function(req, res) {
            Post.find(function(err, posts) {
                if (err)
                    res.send();

                res.json(posts);
            });
        });

    // routes that end in /posts for specific id
    router.route('/posts/:post_id')

        // get the post with that id
        .get(function(req, res) {
            Post.findById(req.params.post_id, function(err, post) {
                if (err)
                    res.send(err);

                res.json(post);
            });
        })

        // update the post with that id
        .put(function(req, res) {
            Post.findById(req.params.post_id, function(err, post) {
                if (err)
                    res.send(err);

                post.postTitle = req.body.postTitle;

                // save the post
                post.save(function(err) {
                    if (err)
                        res.send(err);

                    res.json({ message: 'post updated!' });
                });
            });
        })

        // deletes the post with that id
        .delete(function(req, res) {
            Post.remove({
                _id: req.params.post_id
            }, function(err, post) {
                if (err) {
                    res.send(err);
                }
                res.json({ message: 'post deleted!' });
            });
        });
}
4b9b3361

Ответ 1

Вам нужно добавить "return", чтобы вы не отвечали дважды.

// save post and check for errors
post.save(function(err) {
    if (err) {
        return res.send();
    }
    res.json({ message: 'post created!' });
});

Ответ 2

Это конкретное сообщение об ошибке в значительной степени всегда вызвано из-за ошибки синхронизации при обработке асинхронного ответа, который заставляет вас пытаться отправить данные в ответ после того, как ответ уже отправлен.

Обычно это происходит, когда люди обрабатывают асинхронный ответ внутри экспресс-маршрута как синхронный ответ, и они в конечном итоге отправляют данные дважды.


В одном месте, которое я вижу, вы получите это в любом из путей к ошибкам:

Когда вы это сделаете:

       // save post and check for errors
        post.save(function(err) {
            if (err)
                res.send();

            res.json({ message: 'post created!' });
        });

Если post.save() генерирует ошибку, вы сделаете res.send(), а затем после нее выполните res.json(...). Ваш код должен иметь return или else, поэтому при возникновении ошибки вы не выполняете оба пути кода.

Ответ 3

Таким образом, это может произойти в Express при попытке отправить res.end дважды, что и res.send и res.json. В блоке if(err) вы захотите return res.send(), поскольку res.send запускается асинхронно, а res.json также вызывается. Мне интересно, если вы получаете сообщение об ошибке в своем маршруте delete? Надеюсь, это поможет.

Best!

Ответ 4

Вы используете res.send() или res.json() дважды в одном запросе

это сначала отправляет заголовки, затем тело ответа, а затем заголовки снова. req.next обычно не является функцией, next скорее передается в качестве третьего аргумента промежуточного программного обеспечения. Используйте это, если вы хотите перейти к следующему промежуточному программному обеспечению. (при условии, что вы используете Express Framework)

Ответ 5

Только ради полноты я также упомянул, что: Иногда возникает проблема в промежуточном программном обеспечении, которое вы можете использовать, вызывая app.use.

После проверки очевидных ошибок, упомянутых в предыдущих ответах:

Вы должны удалить все инструкции app.use, а затем повторно ввести их один за другим, чтобы найти проблемный модуль.

Ответ 6

    If you are using res.send() inside any loop, then you need to break it after the use of res.send(). So that it won't allow resetting of the res headers again and again. 
    for e.g : 
    for(){
if(){
res.send();
break;
}
else(){
res.send();
break;
}    
    }
In my case this is the problem and I solved it like this.
    Hope it may help someone in future.
    Thanks