Im new in nodejs, and Im trying to learn by creating an app that has a list of users, that I can add and remove those users. Im using angularjs in frontend to send request to nodejs and after that to mongodb. The problem is that, if I click a lot of times in the button "adduser" a lot of times, my app goes slow.
To interact to mongodb I use:
app.get('/users',function (req, res) {
mongoose.model('Usuario').find(function (err, list) {
res.send(list);
});
});
app.post('/addusuario', function (req,res) {
var usuario = new Usuario(req.body);
usuario.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('Usuario salvo com sucesso');
}
}); });
app.delete('/delusuario/:id', function (req, res) {
var id = req.params.id;
mongoose.model('Usuario').findByIdAndRemove(id , function(err) {
if(err) {
console.log(err);
} else {
console.log('Usuario removido com sucesso!');
}
});
});
Im my angularapp:
app.controller('AppCtrl', function($scope, $http, Data) {
function reload() {
Data.get('users').then(function(data){
$scope.usuarios = data;
console.log(data);
});
};
$scope.addUsuario = function(usuario) {
Data.post('/addusuario', usuario);
reload();
};
$scope.deletarUsuario = function(id) {
Data.delete("/delusuario/"+id).then(function(result) {
});
reload();
};
reload();
});
I dont know why it is becaming slow after I click to add user more than 3 times..
What I see in your code that you are not sending an response back to the user, you should do something after insert or delete in the database. res.end();
You should rewrite your code in the following way:
app.get('/users',function (req, res) {
mongoose.model('Usuario').find(function (err, list) {
res.send(list);
});
});
app.post('/addusuario', function (req,res) {
var usuario = new Usuario(req.body);
usuario.save(function (err) {
if (err) {
console.log(err);
res.json({err: err});
} else {
res.json({ok: true});
console.log('Usuario salvo com sucesso');
}
}); });
app.delete('/delusuario/:id', function (req, res) {
var id = req.params.id;
mongoose.model('Usuario').findByIdAndRemove(id , function(err) {
if(err) {
console.log(err);
res.json({err: err});
} else {
res.json({ok: true});
console.log('Usuario removido com sucesso!');
}
});
});
You block the stack by not returning the response to the client. And this is most probably the cause of your slow request.
Related
I was troubleshooting why my route wasn't working and i came across this.
In my ./routes/jobs.js,
router.delete("/:id", (req, res) => {
Job.findByIdAndDelete(req.params.id, (err, job) => {
if (!err) {
res.json({ msg: "job deleted"});
} else {
console.log(err);
}
});
});
When i tested on postman, Delete - http://localhost:5000/dashboard/60b9405e1ea
Would return the id only 60b9405e1ea and not delete the db job.
I changed my route to "/" and tested it out. using http://localhost:5000/dashboard in postman.
router.delete("/", (req, res) => {
Job.findByIdAndDelete(req.params.id, (err, job) => {
if (!err) {
res.json({ msg: "job deleted"});
} else {
console.log(err);
}
});
It executed the delete request with {msg: "job deleted"}. (Obviously didnt delete db job since no id was given).
Keep in mind in my server.js im using,
app.use("/dashboard", require("./routes/jobs"));
Any help would be appreciated on why /:id is not being executed
As you are getting the id in the console, it's the problem with the query you make.
Try any of these,
Model.remove({ _id: req.body.id }, function(err) {
if (!err) {
message.type = 'notification!';
}
else {
message.type = 'error';
}
});
or
Model.findOneAndRemove({id: req.params.id}, function(err){
});
or a traditional approach:
Model.findById(id, function (err, doc) {
if (err) {
// handle error
}
doc.remove(callback); //Removes the document
})
I'm trying test my node app ,I am able to get post,get and put to work but I can't get delete to work I keep on getting the following error "Type.Error app.address is not a function"
This is my test class :
var supertest = require("supertest");
var should = require("should");
// This agent refers to PORT where program is runninng.
var server = supertest.agent("http://localhost:8000");
// UNIT test begin
describe("Contacts GET unit test",function(){
// #1 should return contacts representation in json
it("should return collection of JSON documents",function(done){
// calling home page api
server
.get("/api/contacts/")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
// HTTP status should be 200
res.status.should.equal(200);
done();
});
});
it("should add a new contact",function(done){
// post to /api/contacts
server.post('/api/contacts')
.send({name:"Contact 99"})
.expect("Content-type",/json/)
.expect(201)
.end(function(err,res){
res.status.should.equal(201);
done();
});
});
it("should update contact",function(done){
// post to /api/contacts
// calling home page api
server.put("/api/contacts/58e275d0aef2392e10eaba6e")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
res.body._id.should.equal("58e275d0aef2392e10eaba6e");
done();
}
);
}
);
it("should delete contact",function(done){
// post to /api/contacts
// calling home page api
const superserver = supertest(server);
server.get("/api/contacts")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
const id = res.body[0]._id;
server.delete("/api/contacts/"+id)
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
res.body._id.should.equal(id);
res.body.should.have.property("name");
done();
}
);
}
);
});
});
and this my main class with all the functionalities :
'use strict';
var _ = require('lodash');
var Contact = require('./contact.model');
// Get list of contacts
exports.index = function(req, res) {
// Connect to the db
Contact.find(function (err, contacts) {
if(err) { return handleError(res, err); }
return res.json(200, contacts);
});
} ;
// Creates a new contact in datastore.
exports.create = function(req, res) {
Contact.create(req.body, function(err, contact) {
if(err) { return handleError(res, err); }
return res.json(201, contact);
});
};
// Updates an existing contact in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Contact.findById(req.params.id, function (err, contact) {
if (err) { return handleError(res, err); }
if(!contact) { return res.send(404); }
var updated = _.merge(contact, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, contact);
});
});
};
// delete an existing contact in datastore.
exports.delete = function(req, res) {
Contact.findById(req.params.id, function (err, contact) {
if(err) { return handleError(res, err); }
if(!contact) { return res.send(404); }
contact.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(201);
});
});
};
function handleError(res, err) {
return res.send(500, err);
};
This what I get in the command line:
I am not sure if it could help but in your test Class the problem seems to be here (l.62):
const id = res.body[0]._id;
it returns undefined so you get a Type.Error
You should try to debug this line and check the return of :
res.body[0]
PS : api\contacts\test\testContancts.js sure about the name file ?
There's no respone for below save method. I wonder why.
app.post('/something', function (req, res) {
mainModel.save(req.body.data ,function(err,data){
if(err){
console.log(err)
}else{
console.log(data)
}
});
});
Here's how my models/main.js look like http://pastebin.com/eQSFXWb5
You didn't return any response after save. you should return response ie. return res.status(400).send().
you can try it
app.post('/something', function (req, res) {
if(!req.body.data) {
return res.status(400).send({masg: 'Invalid data'});
}
var newMainModel = new mainModel(req.body.data);
newMainModel.save(function(err,data){
if(err){
console.log(err)
return res.status(400).send({masg: 'Error occurred'});
}
console.log(data);
return res.status(200).send(data);
});
});
I'm a beginner in Node/Express. I tried to make an CRUD application but stuck at update and delete. I think my router code is problematic but I don't know why. The following code is in my controller, everything works but PUT and DELETE. It always route to GET. I tried to use next(); but it returns this error: Can't set headers after they are sent..
I can make the delete works by using GET /:company_id/delete but it's not a good and standardized solution. How can I get update and delete process worked?
'use strict';
var Companies = require('../../models/companies');
module.exports = function (router) {
// INDEX
// accessed at GET http://localhost:8000/companies
router.get('/', function (req, res) {
Companies.find(function(err, model) {
if (err) {
res.send(err);
}
else {
res.format({
json: function () {
res.json(model);
},
html: function () {
res.render('companies/index', model);
}
});
}
});
});
// CREATE VIEW
// accessed at GET http://localhost:8000/companies/create
router.get('/create', function (req, res) {
res.render('companies/create');
});
// CREATE DATA
// accessed at POST http://localhost:8000/companies
router.post('/', function (req, res) {
var name = req.body.name && req.body.name.trim();
var type = req.body.type && req.body.type.trim();
// VALIDATION
if (name === '') {
res.redirect('/companies/create');
return;
}
var model = new Companies({name: name, type: type});
model.save(function(err) {
if (err) {
res.send(err);
}
else {
res.redirect('/companies');
}
});
});
// READ
// accessed at GET http://localhost:8000/companies/:company_id
router.get('/:company_id', function(req, res) {
Companies.findById(req.params.company_id, function(err, model) {
if (err) {
res.send(err);
}
else {
res.render('companies/read', model);
}
});
});
// UPDATE VIEW
// accessed at GET http://localhost:8000/companies/:company_id/edit
router.get('/:company_id/edit', function(req, res) {
Companies.findById(req.params.company_id, function(err, model) {
if (err) {
res.send(err);
}
else {
res.render('companies/edit', model);
}
});
});
// UPDATE DATA
// accessed at PUT http://localhost:8000/companies/:company_id
router.put('/:company_id', function(req, res) {
Companies.findById(req.params.company_id, function(err, model) {
if (err) {
res.send(err);
}
else {
model.name = req.body.name;
model.type = req.body.type;
model.save(function(err) {
if (err) {
res.send(err);
}
else {
res.redirect('/companies');
}
});
}
});
});
// DELETE
// accessed at DELETE http://localhost:8000/companies/:company_id
router.delete('/:company_id', function (req, res) {
Companies.remove({ _id: req.params.company_id }, function(err) {
if (err) {
res.send(err);
}
else {
res.redirect('/companies');
}
});
});
};
HTML forms only support GET and POST. XMLHTTPRequest supports PUT and DELETE however, so you may have to go that route OR use something like method-override to allow HTML forms to submit using other HTTP verbs.
Heads up, noob coming through. Trying to build a MEAN stack todo list. So far I've gotten everything to work except for the update option. What I've done is set up the application so that it prompts the user to write in the item they want to update. So say they add the item 'ddd.' The update button would then appear beside the item, and then the user would be given a prompt, asking them to enter the new item. The problem is whenever the user does in fact enter the new item to replace the old, nothing happens, and I instead get a 404 error in the command prompt. Any help would be much appreciated. Below you'll find my controller, routes, index.html
routes/api
var Todo = require('./models/todo');
module.exports = function(app) {
// api ---------------------------------------------------------------------
// get all todos
app.get('/api/todos', function(req, res) {
// use mongoose to get all todos in the database
Todo.find(function(err, todos) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
res.json(todos); // return all todos in JSON format
});
});
// create todo and send back all todos after creation
app.post('/api/todos', function(req, res) {
// create a todo, information comes from AJAX request from Angular
Todo.create({
text : req.body.text,
done : false
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// delete a todo
app.delete('/api/todos/:todo_id', function(req, res) {
Todo.remove({
_id : req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
//update to do
app.put('/api/todos/_id', function(req, res) {
Todo.findById(req.params._id, function(err, todos){
todo.text = req.body.text;
console.log(todos);
todos.save(function() {
if (!err) {
res.send(todos);
} else if (err) {
res.send(err);
}
});
});
});
// application -------------------------------------------------------------
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
};
controller
var baselTodo = angular.module('baselTodo', []);
function mainController($scope, $http) {
$scope.formData = {};
// when landing on the page, get all todos and show them
$http.get('/api/todos')
.success(function(data) {
$scope.todos = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
// when submitting the add form, send the text to the node API
$scope.createTodo = function() {
$http.post('/api/todos', $scope.formData)
.success(function(data) {
$('input').val('');
$scope.todos = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
};
// delete a todo after checking it
$scope.deleteTodo = function(id) {
$http.delete('/api/todos/' + id)
.success(function(data) {
$scope.todos = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
};
$scope.updateTodo = function(id) {
$scope.newItem = prompt("Please enter your new item:", "");
$http.put('/api/todos/' + id, {formData: $scope.newItem}).success(function(data) {
$scope.todos = data;
});
$http.get('/api/todos').success(function(data) {
$scope.todos = data;
});
};
};
It looks like, in your routes api:
app.put('/api/todos/_id', function(req, res) {
You forgot the colon in the path, therefore you can't access that variable. Try:
app.put('/api/todos/:_id', function(req, res) {