发送后无法设置标头 - 通过 NodeJs 发布新用户

Posted

技术标签:

【中文标题】发送后无法设置标头 - 通过 NodeJs 发布新用户【英文标题】:Can't set headers after they are sent - Posting new Users through NodeJs 【发布时间】:2016-10-04 14:23:19 【问题描述】:

我正在尝试使用 Google Maps APINodeJsExpressMongoDB 构建应用程序, MongooseAngularJS,我在查看其他相关 SO Q/A 时遇到了无法解决的问题。

基本上,我试图将post 加入我的数据库用户,这些用户由username[latitude, longitude] 识别,他们提交了我认为的某种表单。

当我尝试直接从 Postman 等应用程序post 用户时,一切正常,我可以在我的数据库中看到新用户。

当我尝试在用户提交时直接发布用户时,我的 控制台 中出现以下错误:

/node_modules/mongodb-core/lib/topologies/server.js:766
  catch(err)  process.nextTick(function()  throw err); 
                                             ^
Error: Can't set headers after they are sent.

然后在我的 Google Chrome 控制台中登录:

angular.js:10695 GET http://localhost:3000/users net::ERR_CONNECTION_REFUSED

这是我的观点

<form name="addForm" novalidate>
  <div class="form-group">
       <label for="username">Username
          <span class="badge">All fields required</span>
       </label>
       <input type="text" class="form-control" id="username" 
              placeholder="OldandGold" ng-model="formData.username" required>
   </div>
   <div class="form-group">
      <label for="latitude">Latitude</label>
        <input type="text" class="form-control" id="latitude" 
               value="39.500" ng-model="formData.latitude" readonly>
   </div>
   <div class="form-group">
     <label for="longitude">Longitude</label>
        <input type="text" class="form-control" id="longitude" 
               value="-98.350" ng-model="formData.longitude" readonly>
   </div>

   <button type="submit" class="btn btn-danger btn-block" 
           ng-click="createUser()" ng-disabled="addForm.$invalid">Submit</button>
</form>

这是我的架构

// Pulls Mongoose dependency for creating schemas
var mongoose = require('mongoose');
var GeoJSON  = require('geojson');
var Schema   = mongoose.Schema;

var LocationSchema = new Schema(
                                    name: type: String, required: true,
                                    location: 
                                      type: type : String, required: true,
                                      coordinates : [Schema.Types.Mixed]
                                    ,
                                    created_at: type: Date, default: Date.now,
                                    updated_at: type: Date, default: Date.now
);

// Sets the created_at parameter equal to the current time
LocationSchema.pre('save', function(next)
    now = new Date();
    this.updated_at = now;
    if(!this.created_at) 
        this.created_at = now
    
    next();
);

// Indexes this schema in 2dsphere format (critical for running proximity searches)
LocationSchema.index(location: '2dsphere');

module.exports = mongoose.model('mean-locations', LocationSchema);

这是我的控制器的 createUser 函数

$scope.createUser = function($rootScope, $on) 
        // Grabs all of the text box fields
        var userData = 
            name: $scope.formData.username,
            location: 
                        type: "Point",
                        coordinates: [$scope.formData.latitude, 
                                      $scope.formData.longitude]
            
        ;

        console.log(JSON.stringify(userData));

    // Saves the user data to the db
    $http.post('/users', userData)
        .success(function(data) 

            // Once complete, clear the form (except location)
            $scope.formData.username = "";

        )
        .error(function(data) 
            console.log('Error: ' + data);
        );
;

最后,这是我的路线

app.get('/users', function(req, res) 

        // Uses Mongoose schema to run the search (empty conditions)
        var query = User.find();
        query.exec(function(err, users) 
            if (err)
                res.send(err);

            // If no errors are found, it responds with a JSON of all users
            res.json(users);
        );
);

    // POST Routes
    // --------------------------------------------------------
    // Provides method for saving new users in the db
    app.post('/users', function(req, res) 

        // Creates a new User based on the Mongoose schema and the post body
        var newuser = new User(req.body);

        // New User is saved in the db.
        newuser.save(function(err) 
            if (err)
                res.send(err);

            // If no errors are found, it responds with a JSON of the new user
            res.json(req.body);
        );
    );

使用我的 Stringify Log 我可以看到正确的 json:

"name":"MyPoint","location":"type":"Point","coordinates":["50.064","16.260"]

我对 NodeJs 还很陌生,我不明白为什么会这样。

是什么原因造成的?我该如何解决这个问题?

提前致谢。

【问题讨论】:

【参考方案1】:

问题就在这里,如果出现错误,你必须停止执行。 (注意退货)。例如,如果出现错误,您的代码将发送(res.send)错误并继续执行res.json(),它将以您提到的错误结束,因为您已经设置了标头并发送了响应。

    newuser.save(function(err) 
        if (err)
            return res.send(err);

        // If no errors are found, it responds with a JSON of the new user
        res.json(req.body);
    );

【讨论】:

感谢您的回答。我不再收到错误消息,但似乎没有将新创建的用户保存到数据库中。有什么想法吗? 尝试记录错误。如果出现错误,用户将不会被保存。你也必须为 app.get('/users', ...); 做同样的事情; 完全没有错误。当我使用邮递员发布同一用户时,一切正常。 嗯。在那种情况下,它可能是由您的角度代码引起的问题,我不是很熟悉。我建议您针对该问题提出一个新问题。【参考方案2】:

“错误:发送后无法设置标头。”错误通常表示您正在发送多个响应(使用 express)。

例如,此代码将(尝试)发送两个响应以防出错

app.get('/users', function(req, res) 

    // Uses Mongoose schema to run the search (empty conditions)
    var query = User.find();
    query.exec(function(err, users) 
        if (err)
            res.send(err); // first response

        // If no errors are found, it responds with a JSON of all users
        res.json(users); // second response
    );
);

要解决此问题,请确保在发送响应后退出:

app.get('/users', function(req, res) 

    // Uses Mongoose schema to run the search (empty conditions)
    var query = User.find();
    query.exec(function(err, users) 
        if (err) 
            res.send(err);
            return; // return here!
        

        // If no errors are found, it responds with a JSON of all users
        res.json(users);
    );
);

【讨论】:

感谢您的回答。我不再收到错误消息,但似乎没有将新创建的用户保存到数据库中。有什么想法吗? 你能尝试缩小错误范围吗...也许在 post user 处理程序中喷洒 console.log 看这里***.com/questions/37633218/…

以上是关于发送后无法设置标头 - 通过 NodeJs 发布新用户的主要内容,如果未能解决你的问题,请参考以下文章

在nodejs中发送标头后无法设置标头

UnhandledPromiseRejectionWarning:错误:发送后无法设置标头[重复]

为啥我在 Nodejs 中收到“无法在将标头发送到客户端后设置标头”错误?

将标头发送到客户端后无法设置标头-Nodejs + AWS-S3 getObject

错误:在我初始化会话后发送标头后无法设置标头

发送到客户端后无法设置标头