MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Por que estou recebendo Não é possível definir cabeçalhos depois que eles são enviados para o erro do cliente no Nodejs?


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

Se você atingir essa condição de docs.length == 0 , você enviará uma resposta à solicitação. Mas, seu return está retornando SOMENTE do Post.find() ligue de volta. Não está retornando do seu trendingposts() função.

Então, enquanto isso, essa função continua a ser executada e, eventualmente, chega a este código:
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);
    });

Onde você envia outra resposta para a mesma solicitação. Isso é o que aciona o erro Cannot set headers after they are sent to the client que você vê.

Existem muitas maneiras diferentes de evitar isso, mas provavelmente todas estão relacionadas a como você geralmente limparia essa função. Do jeito que está escrito agora, você basicamente inicia dois caminhos de código assíncronos completamente separados. Ambos começam com Post.find({}) e partir daí. Cada um deles é executado em paralelo e nenhum deles tem ideia do que o outro caminho de código está fazendo. Como tal, você não tem uma maneira concreta de enviar uma resposta de um, mas não de ambos.

Portanto, a maneira de limpar isso provavelmente é não ter dois caminhos de código assíncronos completamente separados. Você precisa coordená-los de alguma forma. Em praticamente todos os casos aqui, você desejará alternar para a interface de promessa para seu banco de dados, pois isso lhe dará muito mais opções para gerenciar seu fluxo de controle. Por exemplo, se por motivos de desempenho, você deseja ter duas operações assíncronas paralelas acontecendo ao mesmo tempo, com promessas, você pode usar Promise.all() ou Promise.allSettled() para monitorar ambos e saber quando eles são feitos e então, com ambos os resultados em mãos, decidir qual resposta enviar.

Ou, se você quiser seqüenciá-los, você pode usar async/await para sequenciar com bastante facilidade as duas operações e, em seguida, quando você fizer um return , ele retornará da função de nível superior e interromperá o fluxo de controle adicional.

Se você quiser manter a interface de retorno de chamada para seu banco de dados, provavelmente terá que aninhar a segunda operação na primeira opção para não iniciar a segunda operação se for fazer res.send({ message: "No posts" }) .