Basic GET Request using Express.js & Mongoose - node.js

I'm working on an assignment to list all of the data in a mongoDB database, and am having trouble finding where I'm going wrong. It seems like a fairly simple problem, but whenever I run the provided mocha test, it keeps throwing 404 errors. Here is the relevant portion of the test:
it('should it able to retrieve all listings', function(done) {
agent.get('/api/listings')
.expect(200)
.end(function(err, res) {
should.not.exist(err);
should.exist(res);
res.body.should.have.length(147);
done();
});
});
And here is my code for the GET request. I've tried a few different ways of coding it, but this is seems like the simplest/most direct way to return the desired data as JSON.
exports.list = function(req, res) {
Listing.find(function(err, listing){
if(err){
res.status(404).send(err);
} else {
res.json(listing);
}})
};
Is there anything else I should be doing? I've been looking at tutorials and basic examples of requests and it seems like it should work, but it doesn't. Any help would be greatly appreciated.

Make sure that the middleware function (the code for GET request) is mapped to /api/listings
I'm not sure about exports.list. It should probably be module.exports
I'm assuming, based on ur code, that ur using the mongoose ODM. In which case, I think you need to pass a query to the find method check this out
You might wanna make sure that you're connected to the database at the time of test initialization and that that completes before the test starts
It always helps to log errors
Checkout express-generator to scaffold a boilerplate express app. Might help to compare it with your app, to check if it's wired correctly

Seems like you are not passing the first parameter to the find method. Only the callback ... try this:
Listing.find({}, function(err, listing) {
if (err) {
res.status(404).send(err);
} else {
res.json(listing);
}
})
I am assuming you want all records which is why we pass an empty object {}.

Related

Execute code on error

I want to execute a code of automated mail whenever there is any kind of error from any of the API.
Though this is possible to write that code in catch block of a remote method but my code base is too long and hence this is not a best fit.
Another issue with this is approach is for API which are not custom remote method and are generated by loopback, it is hard to use catch block with them.
Can someone help me with an easy approach where I need to write code once and the end result will be whenever there is an error in any of my API my code for mail runs automatically.
Got the answer after struggling for a day.
Loopback provides RemoteHook (afterRemoteError) for a model-method,
_modelName_.afterRemoteError( _methodName_, function( ctx, next) {
//...
next();
});
So whenever a particular method returns any error this block of code is executed.
Read more about remote hooks : https://loopback.io/doc/en/lb2/Remote-hooks.html
To make this block of code run every time any method returns error, we can use wildcards
_modelName_.afterRemoteError(** , function( ctx, next) {
//...
next();
});
Read more about wildcards here : https://loopback.io/doc/en/lb2/Remote-hooks.html#wildcards
You should take a look at Loopback https://github.com/strongloop/strong-error-handler
I also strongly suggest integrating a service like Rollbar.

Why does this simple Node, Sequelize Promise code hang?

I'm trying to do a simple command line database transformation with node.js and sequelize. I've simplified my errant code down to the following, but it never returns:
// Set up database connection and models
var models = require('../models_sequelize');
models.User.findOne()
.then(a => {
console.log(a.name);
});
I get a name printed, but then the script hangs. What is wrong? How do I debug this to see what's stuck? I get the impression that there's an orphan promise that's not being fulfilled, but I don't understand where or why. I must be missing something obvious.
If I run the same interactively from the node console, it returns fine.
Sirko's comment re: close() gave me something to go on. I can stop the hanging with the following code:
var models = require('../models_sequelize');
models.User.findOne()
.then(a => {
console.log(a.name);
models.sequelize.close();
})
Alternatively, this seems to work too as I guess it's doing exactly the same thing:
var models = require('../models_sequelize');
models.User.findOne()
.then(a => {
console.log(a.name);
})
.finally(() => {
models.sequelize.close();
});
I also found something about connection pooling timeouts, but I don't think that affects my simple use case. I imagine it'll come into play in more complicated examples.
Would still like to find a good reference as to why this is necessary rather than just my guess.

Express GET route will not work with parameters

I am new to Express and Mongoose. I am currently working on my first project, that is not a tutorial, and I has run into a problem.
I have multiple routes, they are defined in the index.js like this:
app.use('/api/client',require('./routes/client'));
app.use('/api/host',require('./routes/host'));
In the routes, there are multiple verbs that work, like PUT and POST.
Here is the problematic route (I am trying to do more that what is presented here, but what is presented here, does not work as well):
router.get('/ama/:id', function (req, res, next) {
Ama.findById(req.params.id).then(function(Ama){
res.send(Ama);
});
});
This should work, right? It should return the document in the database, with that id. And I have checked if the document excists, probably around a 100 times.
Now, if I simplify the route greatly, removing the id, and make a simple response, the route works:
router.get('/ama', function (req, res, next) {
res.send({type:"GET"});
});
It's so wierd, that as soon as i add the parameter, i get a:
<pre>Cannot GET /api/host/ama</pre>
in Postman.
Any ideas? Mongod is running, my other routes are working.
It looks like you're trying to retrieve this URL:
/api/host/ama?id=SOMEID
However, you have a route declared for URL's that look like this:
/api/host/ama/SOMEID
In other words, the id is part of the path of the URL, and not passed as a query string parameter (that's what /:id means: it's a placeholder for a part of the URL that the route should match).
So either change the request-URL by adding the id to the path (/api/host/ama/58e395a8c6aaca2560089c‌​e7), or rewrite your route handler to something like this:
router.get('/ama', function (req, res, next) {
Ama.findById(req.query.id).then(function(Ama){
res.send(Ama);
});
});
However, I would advise using the former (making the id part of the URL).
There are two problems here:
router.get('/ama/:id', function (req, res, next) {
Ama.findById(req.params.id).then(function(Ama){
res.send(Ama);
})
res.send(req.params.id)*/
});
First of all, res.send(req.params.id) will run before the res.send(Ama); and it will probably send the entire response. You are missing the .exec() method call (see the answer by Cédric De Dycker for details). The res.send() can only be reliably used once. Maybe you want res.write() instead if you want to wrte multiple things. Also you don't handle the promise rejection so you don't handle database errors. To know why you should always handle the promise rejections see this answer: Should I refrain from handling Promise rejection asynchronously?
The parameter should work fine but it seems you missed to add .exec to your query
Ama.findById(req.params.id).exec().then(function(Ama){
res.send(Ama);
})

node async call return data in response

I am new to nodejs so I have a basic question and this is my scanrio
I have a javascript client which is making a http request to a node server to read a value from the database.
Once the node server receives the request it makes a simple db call and returns the data to the client in the response, and this is where the problem is.
router.get('/state', function(req, res){
var result = dbServer.makeDBCall();//Before this line executes and returns the result the next line executes
res.send(result);
}
The database call from the node server is asynchronous, therefore before the result is returned the node server has already sent a blank response to the client. What is the standard/acceptable way of getting this achieved, I know I can block the node thread using async, but then the whole purpose of node is gone right?
It depends on what kind of database node module you are using.
Other than the standard callback approach, there are also the promise way. The pg-promise library is 1 of those kind.
See sample code:
this.databaseConnection.makeDBCall('your query...')
.then(function(dbResponse) {
// Parse the response to the format you want then...
res.send(result);
})
.catch(function(error) {
// Handle error
res.send(error.message);
});
#spdev : I saw 1 of your comments about you being worried about how Node actually knows who to reply the response to, especially when there are multiple requests.
This is a very good question, and to be honest with you - I don't know much about it as well.
In short the answer is yes, Node somehow handles this by creating a corresponding ServerResponse object when a HTTP request comes through. This object seems to have some smartness to tell the Nodejs network stack how to route itself back to the caller when it gets parsed as data packets.
I tried Googling a bit for an answer but didn't got too far. I hope the ServerResponseObject documentation can provide more insight for you. Share with me if you got an answer thanks!
https://nodejs.org/api/all.html#http_class_http_serverresponse
Try below code.
router.get('/state', function(req, res){
var result = dbServer.makeDBCall(function(err,result){
if(!err) {
res.send(result);
}
});
}
Hope this Help.
The dbServer.makeDBCall(); must have a callback that runs when the statement completes executing.
Something like -
dbServer.makeDBCall({query: 'args'}, function(err, result){
if (err) // handle error
res.send(result);
})
You return the response from db from that callback function.
Learn more about callback from here-
nodeJs callbacks simple example
https://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks/

NodeJs request handling on server side

Hi all Currently My System take multiple request as in queue but when first request take too much time than another requested person have to wait until it's not closed Like FCFS (First come First Serve) algorithm.
Now I want something Like that If 5 Request in queue than Next request has give an error server is too much busy right now Please try after some time.
Please let me know any other Technic that can handle request better than these or any other IDEA please share your thoughts May it's Helpful.
Thanks
I don't think its a good idea to serve only one request at a time. Servers are for handling multiple requests. But if you want to limit requests to 5 you can use use closure variable to achieve the same. e.g. this express router:
var noOfActiveReq = 0;
router.get('/handle', function (req, res) {
if(noOfActiveReq > 5) {
return next(new Error("server is too much busy right now Please try after some time"));
}
noOfActiveReq++;
db.get(req.query.id, function(err, result){
noOfActiveReq--;
if(err) return next(err);
res.json(result);
});
});

Resources