NodeJS/Express/Mongoose 出错 Can't set headers after they are sent

Posted

技术标签:

【中文标题】NodeJS/Express/Mongoose 出错 Can\'t set headers after they are sent【英文标题】:NodeJS/Express/Mongoose get error Can't set headers after they are sentNodeJS/Express/Mongoose 出错 Can't set headers after they are sent 【发布时间】:2014-12-23 15:19:25 【问题描述】:

我正在使用 MEAN 堆栈和 Mongoose 来查询 MongoDB 上的数据。第一次调用 /api/Validations 很好,但第二次,它总是得到这个错误:

这是我的代码,server.js:

var express = require('express')
    , app = express()
    , bodyParser = require('body-parser')
    , breezeRoutes = require('./breeze-routes')
    , controller = require('./controller')
    , compress = require('compression')
    , cors = require('cors')
    , errorHandler = require('./errorHandler')
    , favicon = require('static-favicon')
    , fileServer = require('serve-static')
    , http = require('http')
    , isDev = app.get('env') === 'development'
    , logger = require('morgan')
    , port = process.env["PORT"] || 4000;

app.use(favicon());
app.use(logger('dev'));
app.use(compress());
app.use(bodyParser()); // both json & urlencoded  
app.use(cors());          // enable ALL CORS requests
controller.init(app); // Configure  routes for REST API      
app.use(errorHandler);

// create server (in case interested in socket.io)
var server = http.createServer(app);

// Start listening for HTTP requests
server.listen(port); // app.listen( port ); // if we weren't using 'server'

console.log('\nListening on port ' + port);

controller.js:

(function (controller) 
    var mongooseDB = require("./mongooseDB");

    controller.init = configureRoutes;
    function configureRoutes(app)   
        app.get('/api/Validations', getValidations);     
      

    function getValidations(req, res, next) 
        mongooseDB.getValidations(makeResponseHandler(res, next));
    

    function makeResponseHandler(res, next) 
        // returns a function that handles response from a Breeze Mongo query or save
        return function (err, results) 
            if (err) 
                next(err);
             else 
                // Prevent browser from caching results of API data requests
                //res.setHeader('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
                //res.setHeader("Content-Type:", "application/json");
                res.send(JSON.stringify(results));
                res.end();
            

        
     
)(module.exports)

mongooseDB.js

(function (mongooseDB) 
    var schema = require("./schema");
    var validator = require("./validator");
    var mongoUrl = 'mongodb://localhost:27017/dpt';
    var mongoose = require('mongoose');
    var Validations = mongoose.model('Validations', schema.ValidationSchema);

    mongooseDB.getValidations = function (next) 
        mongoose.connect(mongoUrl);
        mongoose.connection.on('open', function () 
            var query = Validations.find();
            query.exec(function (err, docs) 
                mongoose.disconnect();
                if (err) 
                    next(err, null);
                 else 
                    next(null, docs);
                
            );
        );
    ;
)(module.exports)

validationSchema.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var validationSchema = new Schema(
    ValidationID:  type: String, index: 1, required: true, unique: true ,
    Integer:  type: Number, required: true ,
    String: String,
    Date: Date,
    BeforeDate: Date,
    AfterDate: Date,
    Age: Number,
    CreditCard : Number,
    Email: String,
    Phone: String,
    URL: String,
    Zip: String,
    StartsWithDPT: String,
    ContainsDPT: String
,  collection: 'Validations' );
exports.ValidationSchema = validationSchema;

我在堆栈溢出时阅读了所有“发送后无法设置标题”并尝试应用一些方法但没有运气。 请帮帮我。

更新 1:

我认为这是 Mongoose 的问题,因为在我将其更改为使用 MongoDB 后,它工作正常: (函数(数据库) var MongoClient = require('mongodb').MongoClient;

        database.getDb = getDb;
        database.getValidations = getValidations;

        var db = null;
        // todo: get from configuration
        var mongoUrl = 'mongodb://localhost:27017/dpt';
        var mongoOptions = 
            server:  auto_reconnect: true 
        ;

        function getDb(next) 
            if (db) 
                next(null, db);
             else 
                MongoClient.connect(mongoUrl, mongoOptions, function (err, theDb) 
                    if (err) 
                        err.message = (err.message || '') + '. Is the MongoDb server running?';
                        next(err, null);
                     else 
                        db = theDb;
                        next(null, db);
                    
                );
            
        

        function getValidations(next) 
            getDb(function (err, data) 
                if (err) 
                    err.message = (err.message || '') + '. Is the MongoDb server running?';
                    next(err, null);
                 else 
                    data.collection("Validations").find().toArray(function (err1, results) 
                        next(null, results);
                    );;

                
            );
            
)(module.exports)

现在我可以根据需要多次调用 /api/Validations,但这个问题仍然存在,因为这个项目需要 Mongoose。

【问题讨论】:

【参考方案1】:

而不是这个:

return function (err, results) 
            if (err) 
                next(err);
             else 
                // Prevent browser from caching results of API data requests
                //res.setHeader('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
                //res.setHeader("Content-Type:", "application/json");
                res.send(JSON.stringify(results));
            
            res.end();
        

使用这个

return function (err, results) 
            if (err) 
                next(err);
             else 
                // Prevent browser from caching results of API data requests
                //res.setHeader('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
                //res.setHeader("Content-Type:", "application/json");
                res.end(JSON.stringify(results));                    
            

    

【讨论】:

感谢@Suburaj,但实际上,这是我的第一种方法,但没有奏效。我仍然遇到这个问题。我更新了我的问题 @Quoc Nguyen 代码现在正在运行???如果这有用,请不要忘记接受答案.. res.send 无论如何都会调用res.end

以上是关于NodeJS/Express/Mongoose 出错 Can't set headers after they are sent的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS/Express/Mongoose 出错 Can't set headers after they are sent

NodeJS Express Mongoose 返回空 []

nodejs+express+mongoose无法获取数据库数据问题解决

NodeJS Express Mongoose API 的 2018 年 MongoDB 不同计数

如何使用 Mongoose 获取文档数量?

使用 Mongoose 返回更新的集合