web-dev-qa-db-fra.com

Erreur de routage Express.js: impossible de définir les en-têtes après leur envoi

Je ne sais pas vraiment pourquoi je reçois cette erreur. C'est une simple API construite sur express.js pour pouvoir ajouter et supprimer des publications. L'erreur se produit lorsque je déclenche le routeur de suppression. J'ai lu que l'erreur se produit généralement quand il y a deux rappels, cependant, je ne semble pas pouvoir trouver de double rappel.

    _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)

Voici mon routeur 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!' });
            });
        });
}
20
bounty

Vous devez ajouter le «retour» pour ne pas répondre deux fois.

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

Ce message d'erreur particulier est presque toujours dû à une erreur de synchronisation dans le traitement d'une réponse asynchrone qui vous oblige à essayer d'envoyer des données sur une réponse après que la réponse a déjà été envoyée.

Cela se produit généralement lorsque des personnes traitent une réponse asynchrone dans un itinéraire express comme une réponse synchrone et finissent par envoyer des données deux fois.


Je pense que vous obtiendrez un emplacement dans l'un de vos chemins d'erreur:

Quand tu fais ça:

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

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

Si post.save() génère une erreur, vous ferez res.send() et vous ferez res.json(...) après. Votre code doit avoir une return ou une else afin qu'en cas d'erreur, vous n'exécutiez pas les deux chemins de code.

13
jfriend00

Cela peut donc se produire dans Express lorsque vous tentez d'envoyer res.end deux fois, ce que font res.send et res.json. Dans votre bloc if(err), vous souhaiterez utiliser return res.send() car res.send sera exécuté de manière asynchrone et res.json sera également appelé. Je me demande si vous obtenez une erreur dans votre itinéraire delete? J'espère que cela t'aides.

Meilleur!

5
R.A. Lucas

Vous utilisez res.send() ou res.json() deux fois dans la même demande

ceci envoie les en-têtes en premier, suivi du corps de la réponse, puis de nouveau en-tête .req.next n'est généralement pas une fonction, next est plutôt passé comme troisième argument du middleware. Utilisez-le si vous voulez passer au middleware suivant. (en supposant que vous utilisez le framework Express)

3
Jay Thakkar
    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
0
Geek_KK