Node.js only one function executed - node.js

I try to execute two functions in a post request but only one is triggered. The function makeEntry executes but the function afterwards renderEntries does'nt. Can anyone help pls?
Here is the code: https://codepaste.net/bpsxsy

This is due to how callbacks work in Javascript. Here is the part which matters:
app.post('/guestbook_post', urlencodedparser, function(req, res){
makeEntry(req, res, Guestbook);
renderEntries(res, Guestbook);
});
You pass res to both functions. But makeEntry invokes res.send() which means it will end the request and send the response back to the client. However, renderEntries was not yet executed, but still waiting in event loop. It will be executed the next time you make a post request, which will lead to very confusing and buggy behaviour.
To make it work as intendeed, refactor functions makeEntry and renderEntries to return the needed result object and render it to the client once. Something like this:
app.post('/guestbook_post', urlencodedparser, function(req, res){
makeEntry(req, Guestbook, (err, entry) => {
renderEntries(entry, Guestbook, (err, result) => {
res.send(result);
});
});
});

Related

Where does the callback within this express app coming from?

after some freecodecamp I started doing the Express js tutorial from MDN (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Home_page 2) for some backend.
I am stuck at understanding where the callback in the async.parallel is coming from and what is represents.
If I delete the callback the site wont load, so it must have some important meaning but unfortunately I have no glue. Is it calling the function(err, results) { res.render(‘index’, […] }) to make the result availalble for data?
var Book = require(’…/models/book’);
var async = require(‘async’);
exports.index = function(req, res) {
async.parallel({
book_count: function(callback) {
Book.countDocuments({}, callback);
},
[...]
[...]
function(err, results) {
res.render('index', {
title: 'Local Library Home',
error: err, data: results
});
});
};
A Callback is a generic function invoked upon the completion of an asynchronous request. In this particular instance, the Callback is being utilized as a method of getting the data out of the asynchronous request to fill the number of books on your page. These are required because these query's are non-blocking, meaning Javascript will keep executing other surrounding code until the Callback is invoked. If you want more detail on how they work in general look here as previously mentioned by #dnp1204. I hope this answered you question.

In node.js / Express why is a return statement sometimes needed after next() and sometimes not?

In the following test code req.query is checked to see if its value is name=cat. If this is not true next() fires off the next piece of middleware. This is accomplished without including a return statement after next() and it works as expected.
app.get('/test', (req, res, next) => {
if (req.query.name != 'cat') {
next();
}
res.send('it was cat');
});
app.get('/test', (req, res) => {
res.send('it was not cat');
});
However when I change res.send to res.sendFile in the second piece of middleware the behavior is completely different.
app.get('/test', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
});
After the change res.send('it was cat'); in the first piece of middleware fires every time, regardless of the value of name. In addition the second piece of middleware never fires.
This can easily be fixed by adding a return after next() in the first piece of middleware. The behavior becomes predictable again.
app.get('/test', (req, res, next) => {
if (req.query.name != 'cat') {
next();
return;
}
res.send('it was cat');
});
app.get('/test', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
});
Why does this happen with and without the return statement? A return is needed when I use res.sendFile but not when I use res.send. I'm sure I'm missing something obvious but I don't understand the pattern.
This is accomplished without including a return statement after next() and it works as expected.
No, it looks like it works as expected, but it doesn't. For instance, if you retrieve /test without query parameter, or with a query parameter that doesn't equal name=cat, Express will log an error:
Error: Can't set headers after they are sent.
I cannot reproduce your second example; for me, it always returns "it was cat" (in the example without return).
The common rule for any Express handler/middleware is: it should either end the response itself (by calling res.end, res.send, res.render, res.sendFile, etc) or pass the request along using next. In your case, without return, you're doing both. The result of that will be, practically speaking, undefined.
When your listener performs res.send('it was not cat') the entire processing of the request takes place without hitting the trampoline. The next() call never completes until after res.send('it was not cat') finishes. So by the time the code for send('it was the cat') is reached, the response is already sent.
But when your listener performs res.sendFile() the processing of the response is asynchronous. The file has to be read into memory, which is non-blocking I/O in Node. The callback for that I/O is placed into the event queue, and then processing continues. So the next() call returns and then send('it was the cat') executes. All this is before the file is even read into memory. Later when the file is read, the code dutifully attempts to send the response, but it's too late.

MochaJS sending HTTP Request in after hook

I'm trying to send a http delete request to my web server in Mocha's after hook. Here's the relevant code:
after(function() {
console.log('here at after');
request.del('http://localhost:3000/api/deleteAllTasks', function(req, res) {
console.log(req);
});
});
The problem is that the delete endpoint is never being hit. It console.logs "here at after" but never console.logs the request in the callback for request.del. I'm not sure what is causing this; I know the endpoint works as I've sent curl requests to it successfully. Anyone have any ideas? Ultimately, I want this endpoint to clear the DB after this particular test suite runs.
Betting that your script is ending before the asynchronous request is actually made. Try changing your after(function() {... to include the "done" parameter like after(function(done) {... and calling done() within the inner callback.
Here is a new after block that will make your test work. leetibbett is completely correct.
after(function(done) {
console.log('here at after');
request.del('http://localhost:3000/api/deleteAllTasks', function(err, res) {
console.log(res);
done();
});
});

After res.send() event in Restify?

I'm trying to add Bugsnag to my Node Restify service. We have a ton of routes already and such so I'm trying not to add Bugsnag calls all over our code base and I'm also trying to do something global so there's never a mistake where a dev forgets to add the error reporting.
Conceptually I want after any res.send() to get the status code. If the statusCode is >=400 i want to notify Bugsnag by calling Bugsnag.notify. I already check for errors everywhere so no errors ever show up to the clients (browsers, phones, etc) but they do get sent, for example, res.send(401, { message: 'You dont have permission to do that' }) which I'd like to be able to hook into and pass who tried to do that, what route, etc. Problem is I can't get the after event to fire at all:
server.on('after', function (req, res, route, error) {
console.log('AFTER')
});
I think I misunderstand what after is for. It's at the top of my index.js before any routes or other middleware (server.use) is defined.
My general code structure looks something like:
server.post('/foo', function (req, res, next) {
FooPolicy.create(req, function (err) {
if (err) return res.send(err.code, err.data);
FooController.create(req.params, function (response) {
res.send(response.code, response.data)
next();
});
});
});
FooPolicy == checking permissions
FooController == actually creating the model/data
The issue is that the after event is currently treated like any other handler. That means that if you don't call next in every code path, the after event will never be emitted.
In the meantime, adding a next call will cause your after event handler to fire.
if (err) {
res.send(err.code, err.data);
next();
return;
}

How to stop Express.js route from next()?

I have a weird situation...
I have a Express.js, Node.js and Mongoose web app.
One of the routes has a mongoose callback that calls respond.send(...). However, because there is nothing else after the callback, I suspect it goes to next() route automatically.
Ex:
//getItem
app.get('/api/ItemOne', isUserValid, routes.getItem);
//getAnotherItem
app.get('/api/getAnotherItem', isUserValid, routes.getAnotherItem);
//Routes
exports.getItem = function (req, res) {
//console.log ('In getItem');
getItem .findOne({ some_id : some_id}, function(err, getItem ){
//console.log ('In getItem callback');
res.send({
itemName : getItem .itemName,
itemValue : getItem .itemValue;
});
})
});
exports.getAnotherItem = function (req, res) {
//console.log ('In getAnotherItem');
getAnotherItem.findOne({ some_id : some_id}, function(err, getAnotherItemRet){
//console.log ('In getAnotherItem Callback');
res.send({
itemName : getAnotherItemRet.itemName,
itemValue : getAnotherItemRet.itemValue;
});
})
});
I get the following sequence of messages on the console...
In getItem
In getAnotherItem
In getItem callback
In getAnotherItem callback
I am assuming because the route does not finish, it calls next() automatically.
Q: How do I prevent the second route from being called automatically.
Try reversing req and res:
// wrong
exports.getItem = function (res, req) {
// right
exports.getItem = function (req, res) {
(and same for getAnotherItem).
In order to understand why you get messages in that order, we need to know what url are you calling to generate that message.
In any case though, "/api/getItem" does not call "/api/getAnotherItem" for two reasons:
if you call next in "/api/getItem", it will call the next matching route, in this case, it will match either a route on "/api", "/" or nothing at all. the next() function basically calls the route's "parent".
Next() must be called explicitly, if you do not return an answer, express will simply wait indefinitely until res.send is called (which is how it can handle async functions).
It's possible you have some kind of middleware (I.E. used with app.use and not app.get) which could call something like that, but most likely, you are calling both urls at the same time somehow.

Resources