Bruce Gust
asked on
What's the significant of "return" in this code?
Here is a part of my code:
This is what I understand: The order in which this code is being fired is:
req.on("end", () => { -> Event Listener is registered, but not triggered until the end of the overall process
res.setHeader("Content", "text/html"); -> this will fire before the "req.on" because while "req.on" is seen by the process, it's fired asyncronously so it's not processed until the very end.
That's going to be a problem in the the headers have already been set, which result in an error.
However, if I do this:
return req.on("end", () => { - then I don't get an error and the code runs fine.
Why? What's significant about "return" that it allows the code to run in a healthy manner? It seems like it's still and Event Listener and, as far as the Call Stack, it's not being fired until the end and I would expect the same error. But there is no error and I want to understand why.
What do you think?
if (url === "/message" && method === "POST") {
const body = [];
req.on("data", chunk => {
console.log(chunk);
body.push(chunk);
});
[b]req.on("end", () => {[/b]
const parsedBody = Buffer.concat(body).toString();
const message = parsedBody.split("=")[1];
fs.writeFile("message.txt", message, err => {
res.statusCode = 302;
res.setHeader("Location", "/");
return res.end();
});
});
}
res.setHeader("Content", "text/html");
res.write("<html");
res.write("<head><title>My First Page</title></head>");
res.write("<body><h1>Yo, dog!</h1></body>");
res.write("</html>");
res.end();
});
This is what I understand: The order in which this code is being fired is:
req.on("end", () => { -> Event Listener is registered, but not triggered until the end of the overall process
res.setHeader("Content", "text/html"); -> this will fire before the "req.on" because while "req.on" is seen by the process, it's fired asyncronously so it's not processed until the very end.
That's going to be a problem in the the headers have already been set, which result in an error.
However, if I do this:
return req.on("end", () => { - then I don't get an error and the code runs fine.
Why? What's significant about "return" that it allows the code to run in a healthy manner? It seems like it's still and Event Listener and, as far as the Call Stack, it's not being fired until the end and I would expect the same error. But there is no error and I want to understand why.
What do you think?
I am confused about what you are wanting to achieve.
Your if statement is going to fire off the req.on('data') event handler - which will complete in an indeterminate time (async).
The statement after the if is going to execute immediately - i.e. before the data / end events complete.
Yet in these statements you are sending output which will kill any headers you send in the data / end events.
I am guessing this code should be contained in an else
As for the return - not sure which one you are referring to but the return res.end() is not really going to do anything as there is nothing looking for a response from the .on('end'...) handler.
I would recommend taking a read of this article which gives a good overview of the HTTP transaction process
https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/
Your if statement is going to fire off the req.on('data') event handler - which will complete in an indeterminate time (async).
The statement after the if is going to execute immediately - i.e. before the data / end events complete.
Yet in these statements you are sending output which will kill any headers you send in the data / end events.
I am guessing this code should be contained in an else
res.setHeader("Content", "text/html");
res.write("<html");
res.write("<head><title>My First Page</title></head>");
res.write("<body><h1>Yo, dog!</h1></body>");
res.write("</html>");
res.end();
Based on your code you won't get here on a POST to /message because of the redirect to '/' in the end event handler which currently will not work because of the above.As for the return - not sure which one you are referring to but the return res.end() is not really going to do anything as there is nothing looking for a response from the .on('end'...) handler.
I would recommend taking a read of this article which gives a good overview of the HTTP transaction process
https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/
ASKER
Gentlemen!
This is all part of a tutorial that I'm doing on Udemy. Let me give you the whole code so you can see everything that I'm looking at / trying to understand. That way, too, you can see the result of adding the "return" that I'm trying to comprehend, as far as why it makes the difference that it does.
Here's the whole code:
That's the code in its entirety...and this is coming right from the tutorial,
The instructor rightfully acknowledges that the code in its present state will throw an error:
$ node play.js
<Buffer 6d 65 73 73 61 67 65 3d 56 69 76 69 61 6e>
_http_outgoing.js:470
throw new ERR_HTTP_HEADERS_SENT('set ');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the cli
ent
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at fs.writeFile.err (C:\wamp\www\adm\node\play .js:27:13)
at FSReqWrap.oncomplete (fs.js:141:20)
Reason being is that, while the Event Listener that I have in bold is registered (I'm using that term because it's what used in the tutorial. I'm assuming that term refers to the fact that the Event Listener is throwing that functionality into the Call Stack), but it doesn't fire until the "end" of the process is reached. By that point, you can't monkey with the headers because they've already been written.
But...
If I do this:
const http = require("http");
const fs = require("fs");
const server = http.createServer((req, res) => {
const url = req.url;
const method = req.method;
if (url === "/") {
res.write("<html");
res.write("<head><title>My First Page</title></head>");
res.write(
'<body><form action="/message" method="POST"><input type="text" name="message"><button type="submit">Send</button ></form></ body>'
);
res.write("</html>");
return res.end();
}
if (url === "/message" && method === "POST") {
const body = [];
req.on("data", chunk => {
console.log(chunk);
body.push(chunk);
});
return req.on("end", () => {
const parsedBody = Buffer.concat(body).toStri ng();
const message = parsedBody.split("=")[1];
fs.writeFile("message.txt" , message, err => {
res.statusCode = 302;
res.setHeader("Location", "/");
return res.end();
});
});
}
res.setHeader("Content", "text/html");
res.write("<html");
res.write("<head><title>My First Page</title></head>");
res.write("<body><h1>Yo, dog!</h1></body>");
res.write("</html>");
res.end();
});
server.listen(3000);[/code ]
When I add "return" to what I have in bold, at that point, the "return" syntax acts as a quasi "die." This is the situation I was trying to understand that has since been explained by a coworker, but I'm open to any other commentary y'all might want to provide.
What I understand is that the use of "return" in the situation you see above will result in the process coming to screeching halt right after "return res.end." You won't see "Yo, dog!" at all. Plus, you won't see any server errors as far as the headers getting all jacked up.
Is that right?
By adding "return" to the beginning of "req.on("end", () => {," "Yo, dog" will never make it to the Call Stack because of the way "return" will route the flow of the page so it concludes before "Yo, dog" is ever considered.
Correct?
This is all part of a tutorial that I'm doing on Udemy. Let me give you the whole code so you can see everything that I'm looking at / trying to understand. That way, too, you can see the result of adding the "return" that I'm trying to comprehend, as far as why it makes the difference that it does.
Here's the whole code:
const http = require("http");
const fs = require("fs");
const server = http.createServer((req, res) => {
const url = req.url;
const method = req.method;
if (url === "/") {
res.write("<html");
res.write("<head><title>My First Page</title></head>");
res.write(
'<body><form action="/message" method="POST"><input type="text" name="message"><button type="submit">Send</button></form></body>'
);
res.write("</html>");
return res.end();
}
if (url === "/message" && method === "POST") {
const body = [];
req.on("data", chunk => {
console.log(chunk);
body.push(chunk);
});
[b] req.on("end", () => {[/b]
const parsedBody = Buffer.concat(body).toString();
const message = parsedBody.split("=")[1];
fs.writeFile("message.txt", message, err => {
res.statusCode = 302;
res.setHeader("Location", "/");
return res.end();
});
});
}
res.setHeader("Content", "text/html");
res.write("<html");
res.write("<head><title>My First Page</title></head>");
res.write("<body><h1>Yo, dog!</h1></body>");
res.write("</html>");
res.end();
});
server.listen(3000);
That's the code in its entirety...and this is coming right from the tutorial,
The instructor rightfully acknowledges that the code in its present state will throw an error:
$ node play.js
<Buffer 6d 65 73 73 61 67 65 3d 56 69 76 69 61 6e>
_http_outgoing.js:470
throw new ERR_HTTP_HEADERS_SENT('set
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the cli
ent
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at fs.writeFile.err (C:\wamp\www\adm\node\play
at FSReqWrap.oncomplete (fs.js:141:20)
Reason being is that, while the Event Listener that I have in bold is registered (I'm using that term because it's what used in the tutorial. I'm assuming that term refers to the fact that the Event Listener is throwing that functionality into the Call Stack), but it doesn't fire until the "end" of the process is reached. By that point, you can't monkey with the headers because they've already been written.
But...
If I do this:
const http = require("http");
const fs = require("fs");
const server = http.createServer((req, res) => {
const url = req.url;
const method = req.method;
if (url === "/") {
res.write("<html");
res.write("<head><title>My
res.write(
'<body><form action="/message" method="POST"><input type="text" name="message"><button type="submit">Send</button
);
res.write("</html>");
return res.end();
}
if (url === "/message" && method === "POST") {
const body = [];
req.on("data", chunk => {
console.log(chunk);
body.push(chunk);
});
return req.on("end", () => {
const parsedBody = Buffer.concat(body).toStri
const message = parsedBody.split("=")[1];
fs.writeFile("message.txt"
res.statusCode = 302;
res.setHeader("Location", "/");
return res.end();
});
});
}
res.setHeader("Content", "text/html");
res.write("<html");
res.write("<head><title>My
res.write("<body><h1>Yo, dog!</h1></body>");
res.write("</html>");
res.end();
});
server.listen(3000);[/code
When I add "return" to what I have in bold, at that point, the "return" syntax acts as a quasi "die." This is the situation I was trying to understand that has since been explained by a coworker, but I'm open to any other commentary y'all might want to provide.
What I understand is that the use of "return" in the situation you see above will result in the process coming to screeching halt right after "return res.end." You won't see "Yo, dog!" at all. Plus, you won't see any server errors as far as the headers getting all jacked up.
Is that right?
By adding "return" to the beginning of "req.on("end", () => {," "Yo, dog" will never make it to the Call Stack because of the way "return" will route the flow of the page so it concludes before "Yo, dog" is ever considered.
Correct?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks, guys!
res.statusCode 302 tells client to look at(browser to) another url.
Code below is outside if block.
rest.setHeader("Content", "text/html");
According to HTTP status code, 302 has been superseded by 303 and 307.