Точно тук:
Post.find({}, function(err, docs) {
if (docs.length == 0)
return res.send({ message: "No posts" });
Ако изпълните това условие на docs.length == 0
, тогава ще изпратите отговор на заявката. Но вашето return
се връща САМО от Post.find()
обратно повикване. Не се връща от вашите trendingposts()
функция.
И така, междувременно тази функция продължава да се изпълнява и в крайна сметка стига до този код:
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);
});
Където след това изпращате друг отговор на същата заявка. Това задейства грешката Cannot set headers after they are sent to the client
което виждате.
Има много различни начини за предотвратяване на това, но те вероятно всички са свързани с начина, по който обикновено почиствате тази функция. Начинът, по който е написано сега, по същество започвате два напълно отделни пътя на асинхронен код. И двете започват с Post.find({})
и отидете от там. Всеки от тях работи паралелно и никой няма представа какво прави другият кодов път. Поради това нямате конкретен начин да изпратите отговор от един, но не и от двата.
Така че, начинът да изчистите това вероятно е да нямате две напълно отделни пътеки на асинхронен код. Трябва да ги координирате по някакъв начин. В почти всички случаи тук ще искате да преминете към обещаващия интерфейс към вашата база данни, тъй като това ще ви даде много повече опции за управление на вашия контролен поток. Например, ако от съображения за производителност искате да имате две паралелни асинхронни операции, изпълняващи се наведнъж, с обещания, можете да използвате Promise.all()
или Promise.allSettled()
за да наблюдавате и двете и да знаете кога са готови и след това, с двата резултата в ръка, да решите кой отговор да изпратите.
Или, ако искате да ги подредите, можете да използвате async/await
за доста лесно подреждане на двете операции и след това, когато направите return
, той всъщност ще се върне от функцията от най-високо ниво и ще спре по-нататъшния контролен поток.
Ако искате да се придържате към интерфейса за обратно извикване към вашата база данни, тогава вероятно ще трябва да вложите втората операция в първата опция, така че да не стартирате втората операция, ако ще направите res.send({ message: "No posts" })
.