Node.js Tips — Modules, Request Bodies, Reading Lines, and More

John Au-Yeung - Jan 26 '21 - - Dev Community

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() {
    //...
  }
};
Enter fullscreen mode Exit fullscreen mode

module.exports indicates that we’re exporting the properties inside.

Then we can import it by writing:

const `fns` = require('./`fns`');
`fns.foo();`
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

Then we can run:

npm run server -- --port=1234
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

For example, we can write:

const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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();
  });
}
Enter fullscreen mode Exit fullscreen mode

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');
  //...
})();`
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .