AndreaM16 AndreaM16 - 6 months ago 17
Node.js Question

Can't set headers after they are sent - Posting new Users through NodeJs

I'm trying to build an application using Google Maps API, NodeJs, Express, MongoDB, Mongoose and AngularJS and I'm facing a problem that I wasn't able to solve looking at other related SO Q/A.

Basically, I'm trying to

post
into my db users identified by an
username
and
[latitude, longitude]
who submit a certain form that I have in my view.

When I try to
post
users directly from applications like Postman everything goes ok, I'm able to see new users in my db.

When, instead, I try to post users directly when they submit, I get the following error in my Console:

/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.


and the following log in my Google Chrome Console:

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


Here is my View:

<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>


Here is my Schema:

// 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);


Here is my Controller's createUser function:

$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);
});
};


And, finally, here are my routes:

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);
});
});


Using my
Stringify Log
I'm able to see a proper json:

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


I'm pretty new to NodeJs and I don't understand why this keeps happening.

What does cause this? How Can I solve this?

Thanks In Advance.

Answer

The problem is here, you have to stop execution if there is an error. (Note the return). For example if there's an error, in your code will send (res.send) the error and continues executing res.json() what it will end with the error you mentioned, because you have already set the header and send the response.

    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);
    });
Comments