MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Warum erhalte ich in Nodejs die Meldung Cannot set headers after they send to the client error?

Genau hier:

Post.find({}, function(err, docs) {
    if (docs.length == 0)
        return res.send({ message: "No posts" });

Wenn Sie diese Bedingung von docs.length == 0 treffen , dann senden Sie eine Antwort auf die Anfrage. Aber Ihre return kommt NUR von Post.find() zurück zurückrufen. Es kommt nicht von Ihren trendingposts() zurück Funktion.

In der Zwischenzeit wird diese Funktion also weiter ausgeführt und gelangt schließlich zu diesem Code:

var mysort = { score: -1 };
Post.find({})
    .populate("postedBy")
    .populate("comments.postedBy")
    .populate("comments.incomments.postedBy")
    .populate("comments.likes")
    .sort(mysort)
    .limit(10)
    .exec((er, result) => {

        res.json(result);
    });

Wo Sie dann eine weitere Antwort auf dieselbe Anfrage senden. Das löst den Fehler Cannot set headers after they are sent to the client aus die du siehst.

Es gibt viele verschiedene Möglichkeiten, dies zu verhindern, aber sie hängen wahrscheinlich alle damit zusammen, wie Sie diese Funktion im Allgemeinen bereinigen würden. So wie es jetzt geschrieben ist, starten Sie im Wesentlichen zwei völlig separate asynchrone Codepfade. Beide beginnen mit Post.find({}) und geh von dort. Sie laufen jeweils parallel und keiner hat eine Ahnung, was der andere Codepfad tut. Daher haben Sie keine konkrete Möglichkeit, eine Antwort von einem zu senden, aber nicht von beiden.

Der Weg, dies zu bereinigen, besteht also wahrscheinlich darin, nicht zwei vollständig getrennte asynchrone Codepfade zu haben. Sie müssen sie irgendwie koordinieren. In so ziemlich allen Fällen möchten Sie hier auf die Promise-Schnittstelle zu Ihrer Datenbank umschalten, da Ihnen dies viel mehr Optionen zum Verwalten Ihres Kontrollflusses bietet. Wenn Sie beispielsweise aus Leistungsgründen zwei parallele asynchrone Operationen gleichzeitig mit Promises ausführen möchten, können Sie Promise.all() verwenden oder Promise.allSettled() um beide zu überwachen und zu wissen, wann sie fertig sind, und dann, mit beiden Ergebnissen in der Hand, zu entscheiden, welche Antwort gesendet werden soll.

Oder, wenn Sie sie sequenzieren möchten, können Sie async/await verwenden um die beiden Operationen ziemlich einfach zu sequenzieren und dann, wenn Sie eine return machen , wird es tatsächlich von der Funktion der obersten Ebene zurückkehren und den weiteren Kontrollfluss stoppen.

Wenn Sie bei der Callback-Schnittstelle zu Ihrer Datenbank bleiben möchten, müssen Sie wahrscheinlich die zweite Operation in die erste Option verschachteln, damit Sie die zweite Operation nicht starten, wenn Sie res.send({ message: "No posts" }) .