So I'm trying to set up a basic Todo list/CRUD application using the MEAN stack (Angular, MongoDB, Nodejs, Express) and I keep running into trouble when I switch around the routes and models in the directory and try to load up the application via node server on my command prompt. When I move anything the error below is what I get via a command prompt error. Just an FYI, I'm a total NOOB.
App listening on port 3000
GET /api/todos 404 2ms
GET /api/todos 500 7ms - 1.36kb
ReferenceError: Todo is not defined
at app.delete.Todo.remove._id (C:\Users\Basel\WebstormProjects\TEST\node-tod
o-tut1-starter\server.js:41:3)
at callbacks (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starter\no
de_modules\express\lib\router\index.js:164:37)
at param (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starter\node_m
odules\express\lib\router\index.js:138:11)
at pass (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starter\node_mo
dules\express\lib\router\index.js:145:5)
at Router._dispatch (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-sta
rter\node_modules\express\lib\router\index.js:173:5)
at Object.router (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starte
r\node_modules\express\lib\router\index.js:33:10)
at next (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starter\node_mo
dules\express\node_modules\connect\lib\proto.js:193:15)
at Object.methodOverride [as handle] (C:\Users\Basel\WebstormProjects\TEST\n
ode-todo-tut1-starter\node_modules\express\node_modules\connect\lib\middleware\m
ethodOverride.js:48:5)
at next (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starter\node_mo
dules\express\node_modules\connect\lib\proto.js:193:15)
at multipart (C:\Users\Basel\WebstormProjects\TEST\node-todo-tut1-starter\no
de_modules\express\node_modules\connect\lib\middleware\multipart.js:86:27)
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);
});
});
});
// 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)
});
(Assuming you send correct _id from client) you have to reconstruct the _id as BSON object.
Do not know what db-driver you use, but in mongoskin it goes like that:
var mongo = require('mongoskin');
var BSON = mongo.BSONPure;
...
var proper_id = BSON.ObjectID(req.params.todo_id)
In mangoose try following:
var todo = Todo.find({_id : req.params.todo_id});
todo.remove(callback(err, todo)); // callback is optional
Related
Newbie here. I'm trying to send data I received from making making an API call (when the user requests the zoopla page) into an index.ejs view. I'm trying to pass the graph_url by passing it in the res.render.
The graph_url logs correctly, so the API call is coming back, however I get the following error in my terminal:
ReferenceError: graph_url is not defined
Here is my index.js request for the page:
app.get('/zoopla', function(req, res){
request(zoopla, function(err, res, data){
var data = JSON.parse(data);
var graph_url = data.area_values_url
console.log(graph_url);
});
res.render('index', { title : "zoopla", graph : graph_url});
});
graph_url is not defined because is out of the local scope, and also you are trying to render the page before the previous async request() call complete.
try with:
app.get('/zoopla', function(req, res){
request(zoopla, function(err, res, data){
if (err) {
/* handle errors */
}
var data = JSON.parse(data);
var graph_url = data.area_values_url
console.log(graph_url);
res.render('index', { title : "zoopla", graph : graph_url});
});
});
My setup is as follows:
posting to /register will take the arguments and register a user via passport and mongoose. If this returns an UserExistsError the server sends this info to the client (via http error handling).
However the server also displays a 500 server error which should not occur.
This is because of the next() which as far as I understand routes the client to /register. /register itself does not exists as a page (only as the postadress as stated in the code)
So my question is: How to handle the response to not be an error or supress it? Can I use something else instead of next() to stop the redirect to /register? I just want the server to stop doing anything/going out of that function at that point.
Code:
app.post('/register', function(req, res, next) {
console.log('server registering user');
User.register(new User({username: req.body.username}), req.body.password, function(err) {
let tempstring = ""+err;
if(tempstring.indexOf("UserExistsError") !== -1){
return next(err); //get out of the function and into normal operation under '/'
}
});
});
This topic is bugging me and I might just missunderstand something trivial.
Even if /register is a post only route you still need to send a response. If you don't send a response of some kind, the request will hang and eventually timeout in the browser. I would suggest sending a json response like so.
app.post('/register', function(req, res, next) {
console.log('server registering user');
User.register(new User({username: req.body.username}), req.body.password, function(err) {
let tempstring = ""+err;
if(tempstring.indexOf("UserExistsError") !== -1){
return next(err); //get out of the function and into normal operation under '/'
}
res.json({message: 'message here'});
});
});
This will send a 200 OK reponse with some json in the body.
If you just want to pass the request down the line you need to call next without an err object like so.
app.post('/register', function(req, res, next) {
console.log('server registering user');
User.register(new User({username: req.body.username}), req.body.password, function(err) {
let tempstring = ""+err;
if(tempstring.indexOf("UserExistsError") !== -1){
return next(err); //get out of the function and into normal operation under '/'
}
//call next without an error
next();
});
});
I am not sure if this is what you are trying to achieve, but if there is no route that matches it will just go to an error 500.
I've been trying to get a simple nodejs API with CRUD functionality working. I'm using express, and 'monk' package for communicating with mongodb. I've successfully pulled data with a GET request.
I'm unable to get a post() function to work. I'm able to insert new documents to mongo when the insert request is called from a GET request that inserts a doc every time it's called. However, no matter what I do, with or without an actual insert request, my post is returning a 400.
Here's my route file:
var express = require('express');
var router = express.Router();
/* GET hours page. (for users to submit hours) */
router.get('/', function (req, res) {
var db = req.db;
var collection = db.get('entries');
collection.find({}, /*{limit:20}, */function (err, docs) {
if (err) {
console.log('couldn\'t load entries');
}
res.json(docs);
});
});
/* POST hours page. (for users to submit hours) */
router.post('/', function (req, res) {
if (!(req.body.job || req.body.code || req.body.hours)) {
handleError(res, 'Invalid user input', 'Must complete input', 400);
}
var db = req.db;
var collection = db.get('entries');
var newEntry = req.body;
collection.insert(newEntry, function (err, docs) {
if (err){
handleError(res, err.message, 'Failed to create new entry');
}
res.json(docs);
});
});
module.exports = router;
I really don't know why ever single post request is returning a 400. I'm thinking it's a problem with my main file, but it has barely been altered from the initial express generated file.
You if condition is wrong. !(req.body.job || req.body.code || req.body.hours) should be !(req.body.job && req.body.code && req.body.hours).
And are you sure you have really post anything? Check the Content-Type of your requests, which should be application/x-www-form-urlencoded;.
I recommand using supertest to test your app. The usage is very simple.
import request = require("supertest");
import should = require("should");
import app = require("../youApp");
describe("POST /foo", () => {
it("should post something", done => {
request(app)
.post("/foo")
.send({job: "my job", code: "...", "hours"})
.expect(200, done);
});
});
Somthing more
replace var with const .
use arrow function instead of function(req, res).
I have a very basic POST route that creates a new user out of the given data.
Here's how I save it:
app.post('/create', function(req, res){
var firstUser = new models.User(req.body);
firstUser.save();
});
My Mongoose User schema has a few validation options, which work. If I pass the wrong data, validation fails and the user isn't created.
But there's a problem: Mongoose's save() function is asynchronous, so how do I let the client now the validation failed?
The post function will be done by then.
You should have a look at Mongoose documentation. Because save method is asynchronous it takes a callback as parameter. This is where you should check for errors.
app.post('/create', function(req, res){
var firstUser = new models.User(req.body);
firstUser.save(function (err) {
if (err) {
res.send(500, { error: 'Saving first user failed!' });
} else {
res.send({ success: 'Saved!' });
}
})
});
I am using node-mongodb-native driver. I tried
collection.findOne({email: 'a#mail.com'}, function(err, result) {
if (!result) throw new Error('Record not found!');
});
But the error is caught by mongodb driver and the express server is terminated.
What's the correct way for this case?
=== Edit===
I have the code below in app.js
app.configure('development', function() {
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
});
app.configure('production', function() {
app.use(express.errorHandler());
});
Related code in node_modules/mongodb/lib/mongodb/connection/server.js
connectionPool.on("message", function(message) {
try {
......
} catch (err) {
// Throw error in next tick
process.nextTick(function() {
throw err; // <-- here throws an uncaught error
})
}
});
The correct use is not to throw an error, but to pass it to next function. First you define the error handler:
app.error(function (err, req, res, next) {
res.render('error_page.jade');
})
(What's this talk about error being depracated? I don't know anything about that. But even if then you can just use use. The mechanism is still the same.).
Now in your route you pass the error to the handler like this:
function handler(req, res, next) {
collection.findOne({email: 'a#mail.com'}, function(err, result) {
if (!result) {
var myerr = new Error('Record not found!');
return next(myerr); // <---- pass it, not throw it
}
res.render('results.jade', { results: result });
});
};
Make sure that no other code (related to the response) is fired after next(myerr); (that's why I used return there).
Side note: Errors thrown in asynchronous operations are not handled well by Express (well, actually they somewhat are, but that's not what you need). This may crash your app. The only way to capture them is by using
process.on('uncaughtException', function(err) {
// handle it here, log or something
});
but this is a global exception handler, i.e. you cannot use it to send the response to the user.
I'm guessing that the error is not caught. Are you using an Express error handler? Something like:
app.error(function (err, req, res, next) {
res.render('error-page', {
status: 404
});
More on error handling in Express: http://expressjs.com/guide.html#error-handling
In terms of checking for errors off mongodb, use '!error' for success as opposed to '!result' for errors.
collection.findOne({email: 'a#mail.com'}, function(err, result) {
if (!error) {
// do good stuff;
} else {
throw new Error('Record not found!');
}
});
As for the custom 404, I've yet to do that in node and express, but I would imagine it would involve "app.router".