0
votes

Comment sortir après la réponse dans Nodejs avec Express?

C'est ma première fois poser une question sur Stackoverflow. Désolé si j'ai fait des erreurs de poster.

J'essaie de quitter une fonction après avoir envoyé une réponse pour éviter de continuer à traverser la fonction. P>

nœud -v = v12.6.0 p>

express = ^ 4.17.1 p>

mongoose = ^ 5.6.6 p> xxx pré>

fonction continue d'exécuter une autre partie du code de fonction après un retour. P >

Je reçois aussi "Impossible de définir des en-têtes après leur envoi à l'erreur du client" sur le nœud. Je suppose, empêchant la fonction de continuer après l'envoi d'une réponse corrigera cela aussi? P>

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client


13 commentaires

Eh bien, à tout moment, vous effectuez une res.Send arrêtera votre fonction et aucun retour à la fin


Vous pouvez le faire comme si (err) Renvoyer res.Status.send .... dans les deux erreurs de traitement


Bonjour, merci pour votre réponse. J'ai essayé de supprimer les retours et de retourner res.Status.send. Les deux manières continuent toujours de excuser le code après RES.


Parce que vous ne manipulez que ERR, ne reviendrai jamais s'il n'y a pas d'erreur que vous devez envoyer res.Status (200) .Send ({Message: «Succès ou autre chose que vous aimez '})


@Nemer a eu pour travailler! J'ai fini par sauvegarder res.Status.Sentre dans une variable et retourner cette variable après que tous mes chèques de requête sont terminés.


Vous ne devriez pas mettre une réponse à la question. Les questions ici ne sont que pour les questions. Si vous souhaitez partager une réponse à votre propre question qui est différente de celle des autres réponses que vous avez, publiez votre propre réponse (cela est autorisé ici). Veuillez supprimer votre solution de votre question. Il n'appartient pas là.


En outre, je ne vois pas comment votre solution résout le problème de toute façon. Vous avez toujours plusieurs chemins de code pouvant appeler res.Send () plusieurs fois. Je ne vais pas en discuter plus loin dans les commentaires ici. Veuillez supprimer votre solution de la question.


@ Jfrage00, je ne savais pas que je pouvais répondre à mes propres questions. Oui, il existe plusieurs chemins de code pouvant appeler res.Send () mais ma solution ne renvoie pas chaque res.Send () et ne renvoyant qu'une seule res.Send (). Je suis plus que ouvert pour de meilleures solutions, mais c'est comme ça que je l'ai eu pour travailler pour le moment.


Votre erreur n'a rien à voir avec la valeur de retour. Cela concerne Calling res.Send () plusieurs fois pour la même demande.


@ jfriend00 je vois, comment alliez-vous à propos de res.Send () avec plusieurs requêtes de DB dans une demande de critère de fin?


Pouvez-vous montrer le code de votre gestionnaire de demande complète dans votre question? Ce que vous montrez maintenant ne présente pas le problème tout seul, nous ne pouvons donc pas vous montrer facilement comment le réparer.


Oui sûr, je vais mettre à jour ma question. Comment puis-je actuellement fonctionner, mais comme vous l'avez mentionné avant probablement pas la meilleure solution.


Ok, j'ai écrit une réponse basée sur le code que vous montrez maintenant


4 Réponses :


-1
votes

Le message d'erreur indique que, Res peut être envoyé une fois qu'il a été envoyé. Alors retournez-le avec la réponse. xxx


4 commentaires

Le vrai problème est que ce code gars est ses conditions. Lorsque si (err) est vrai, alors sinon si (! Données) sera également vrai. donc la réponse est invoquée deux fois


@ Doc-Han Yup j'ai compris que mon if (! Données) revient toujours vrai. C'était l'un des problèmes, mais j'ai fini par sauvegarder le res.Status.La une variable et retourner une fois que toutes mes vérifications de requête sont finies.


Pensez-vous que c'est une bonne façon d'y aller?


@ Doc-Han La seule chose qui est un problème, je peux voir en ce moment, c'est que je n'envoie toujours qu'une erreur. S'il y a plusieurs erreurs, la réponse d'erreur existante sur la variable sera écrasée. Je pourrais potentiellement changer le fichier .Send ({message: ''}) à .send ({message: []}) et appendez des messages d'erreur. Puis retournez la réponsevariable



0
votes

L'erreur est à la suite de votre condition. Par conséquent, les deux blocs de code sont exécutés entraînant l'envoi de la réponse deux fois. Pour résoudre ce problème, changez votre code ci-dessous.

Category.find({label: category}).exec(function(err, data) {
    if(err) {
        res.status(400).send({message: 'Error finding category.'});
    } else if(data.length>0) {
       //there is no data with that label - Hence, create one
       var newCategory = new Category({label: category, description: '', keywords: ''});
        newCategory.save(function(err, data){
            if(err) {
                //if error
                res.status(400).send({message: 'Error saving new category.'});     
            }else{
                //if item saves
                res.status(200).send({message: 'Item saved'});
            }
        })
    }else{
      //there is a data with that label availble - do something else
        res.status(200).send(data)
    }
});


2 commentaires

Non, le problème réel est que le retour est à l'intérieur d'une fonction interne (asynchrone est également un problème, mais la fonction interne est plus fondamentale). Il vous manque un gros indice: la ligne de commentaire en bas qui dit // plus de choses ici, cela est exécuté au lieu d'exister.


@slebetman oui! Vous semblez avoir cette question plus que quiconque.



0
votes

Il y a deux problèmes avec le flux de votre logique. Tout d'abord est que retour code> ne renvoie qu'une fonction. Il ne renvoie pas la fonction qui appelle une fonction ou la fonction qui définit une fonction.

Fondamentalement, votre code est le suivant: p> xxx pré>

réécrit pour ne pas utiliser de fonctions anonymes Pour préciser ce qui se passe vraiment p> xxx pré>

afin que vous puissiez maintenant voir que vous n'appelez pas retour code> n'importe où dans Yourwunction () code>. p>

Le deuxième problème est que catégorie.find (). Exec () code> est asynchrone. Cela signifie qu'il revient immédiatement et laissez n'importe quel code ci-dessous exécuté avant d'appeler FindCallback () code>. Pour résoudre le problème ASYNC, déplacez Morestuffdownhere () Code> Intérieur FindCallback () CODE>. P>

Par conséquent, le changement le plus simple pour obtenir votre fonctionnement de flux de votre programme est de bouger MORESTUFFDOWERE CODE>: P>

async function yourFunction() {
    // ...

    var status = await addNewCategory(category);
    switch (status) {
        case 'FIND_FAILURE':
            res.status(400).send({message: 'Error finding category.'});
            return;
        case 'SAVE_FAILURE':
            res.status(400).send({message: 'Error saving new category.'});
            return;
    }

    // More stuff down here ...
}


1 commentaires

Merci pour votre réponse et votre explication. Je vais donner ça un aller!



0
votes

L'erreur que vous signalez se produit lorsqu'il existe des chemins de code pouvant envoyer une réponse plus d'une fois. Vous obtenez une seule et une seule réponse par demande. Donc, appeler res.Send () plus d'une fois est une seule fois que vous obtenez cette erreur.

empêcher cela lorsque vous avez un certain nombre d'opérations asynchrones nécessite un peu plus de travail que vous devez faire Assurez-vous que tout votre code est correctement séquencé et que toutes les chemins d'erreur sont correctement terminés (le traitement ultérieur ne se produit pas). En général, ce code est beaucoup plus facile à écrire avec des interfaces basées sur des promesses pour vos opérations asynchrones, mais que vous n'utilisez pas l'interface Promise sur votre base de données, je vais montrer comment vous pouvez le faire avec votre interface de rappel existante. En règle générale, cela implique beaucoup de nidification à l'intérieur des rappels asynchrones et très prudent si / sinon et retour autour des conditionnels et des erreurs.

Votre code est soumis à cette erreur parce que vous êtes Exécution catégorie.find () et book.find () en parallèle. Vous n'attendez pas le code () pour terminer avant de faire les opérations du livre. Si le code de la catégorie provoque une erreur, vous enverrez cette réponse d'erreur, mais continuez de continuer avec le code de livre qui enverra ensuite sa réponse. Au lieu de cela, vous devez vous assurer que s'il y a une erreur avec la catégorie, vous n'exécutez pas du tout le code de livre. Pour l'interface de rappel ordinaire sur votre base de données, cela signifie imbriquer le code de livre à l'intérieur d'un rappel du code de la catégorie. Pour rendre cela plus simple à écrire, je mets le code de catégorie dans sa propre fonction qui a un rappel d'achèvement que nous pouvons utiliser pour savoir quand tout est terminé.

Voici un moyen de le faire: xxx


0 commentaires