Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Like any kind of apps, there are difficult issues to solve when we write Node apps.
In this article, we’ll look at some solutions to common problems when writing Node apps.
How to Include Functions from Other Files
We can include functions from other files if we export the function from a module and then import them.
For example, we can write:
fns.js
module.exports = {
foo() {
//...
}
};
module.exports
indicates that we’re exporting the properties inside.
Then we can import it by writing:
const `fns` = require('./`fns`');
`fns.foo();`
We use the require
keywords to import the fns.js
module.
We don’t need the file extension.
Using Node.js require vs. ES6 import/export
require
is the most versatile way to import modules and it’s supported by all versions of Node.
ES6 imports and exports are supported natively only by the most recent versions of Node.
Therefore, require
is still the best bet until our apps are running on the latest version of Node.
Sending Command-Line Arguments to npm script
We can send command line arguments to an NPM script by using the --
characters.
For example, if we have the following in package.json
:
"scripts": {
"server": "node server.js"
}
Then we can run:
npm run server -- --port=1234
Retrieve POST Query Parameters in an Express App
We can retrieve POST query parameters in an Express app by installing the body-parser
package.
To install it, we run:
npm install --save body-parser
For example, we can write:
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
bodyParser.json()
will parse JSON payloads.
And bodyParser.urlencoded
will parse URL encoded payloads.
‘Can’t set headers after they are sent to the client’ Error
We should make sure that we don’t send a response more than once in our app.
For instance, we should write:
const foo = (request, response, next) => {
request.params = {
a: "b"
};
next();
};
const bar = function(request, response, next) => {
response.setHeader("Content-Type", "text/html");
response.write("hello world");
response.end();
};
app.use(foo);
app.use(bar);
Anything that modifies the response should be placed last.
This way, we don’t send the response more than once.
Anything that calls next
shouldn’t modify the response so that we won’t call any middleware that does send the response after it.
Convert an Existing Callback API to Promises
We can convert any async callback to a promise with the Promise
constructor.
For instance, we can write:
const run = () => {
return new Promise((resolve, reject) => {
//...
resolve();
});
}
We return a promise in our run
function so we can use it with async
and await
or then
.
Also, we can use the util
package’s promisify
method to convert functions that take Node style callbacks to return a promise.
For instance, we can write:
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
(async () => {
const data = await `readFile('/foo.txt');
//...
})();`
We convert the async readFile
method to a promise by using the util.promisify
method.
Then we get the data from reading the file with await
.
Read a File One Line at a Time
To read a file one line at a time, we can use the readline
module.
For example, we can write:
const fs = require('fs');
const readline = require('readline');
const readLineByLine = async () => {
const fileStream = fs.createReadStream('foo.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
console.log(line);
}
}
readLineByLine();
We call createInterface
to get an iterator with the lines, then we use the for-await-of loop to loop through the lines.
Also, we can create a read stream by writing:
const readline = require('readline');
readline.createInterface({
input: require('fs').createReadStream('file.in')
});
lineReader.on('line', (line) => {
console.log(line);
});
We use the createInterface
like the last example, but we call on
to listen to the line
event which has the line that’s read.
Conclusion
We can export and import files to include functions from other JavaScript files.
Reading a file one line at a time can be done with the readline
library.
Also, we should make sure that we don’t send a response more than once in our Express app.
The body-parser
package lets us parse request payloads in an Express app.