sql >> データベース >  >> NoSQL >> MongoDB

Nodejsのクライアントエラーに送信された後、ヘッダーを設定できないのはなぜですか?

    ここに:

    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

    これを防ぐにはさまざまな方法がありますが、それらはすべて、この関数を一般的にクリーンアップする方法に関連している可能性があります。現在の記述方法では、基本的に2つの完全に別個の非同期コードパスを開始します。どちらもPost.find({})で始まります そこから行きます。それらはそれぞれ並列で実行され、他のコードパスが何をしているのかまったくわかりません。そのため、一方から応答を送信する具体的な方法はありませんが、両方を送信することはできません。

    したがって、これをクリーンアップする方法は、2つの完全に別個の非同期コードパスを持たないことです。何らかの方法でそれらを調整する必要があります。ここでのほとんどすべての場合、データベースへのpromise-interfaceに切り替える必要があります。これにより、制御フローを管理するためのより多くのオプションが提供されます。たとえば、パフォーマンス上の理由から、promiseを使用して2つの並列非同期操作を同時に実行する場合は、Promise.all()を使用できます。 またはPromise.allSettled() 両方を監視し、いつ完了したかを確認してから、両方の結果を手元に置いて、送信する応答を決定します。

    または、シーケンスを作成する場合は、async/awaitを使用できます。 2つの操作をかなり簡単に順序付けてから、returnを実行すると、 、実際には最上位の機能から戻り、それ以上の制御フローを停止します。

    データベースへのコールバックインターフェイスを使い続けたい場合は、res.send({ message: "No posts" })




    1. MongoDBドキュメントからフィールドを完全に削除するにはどうすればよいですか?

    2. MongoDB $ setDifference

    3. マングースが空の配列を返す

    4. 別のモデルで定義されたマングースデータベースのスキーマを取得する方法