Categories
Node.js Tips

Node.js Tips — Related Documents, Unzipping Files, and Parsing HTML

Spread the love

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.

Creating Rooms in Socket.io

To create rooms in socket.io, we just have to join a room by name.

It doesn’t have to be created.

For instance, we can write:

socket.on('create', (room) => {
  socket.join(room);
});

We listen to the create event with the room name.

We get the room parameter with the room we want to join.

Then we can emit the event so join is run:

socket.emit('create', 'room');

'create' is the event name.

'room' is the room name.

Use populate with Multiple Schemas in Mongoose

We can chain the populate calls to select multiple related documents.

For instance, we can write:

Person.find()
  .populate('address')
  .populate('phone')
  .exec((err, results) => {
    //...
  });

to get the Person with the address and phone models.

Then we get all the related documents in the results .

Also, we can call populate with a space-delimited string to specify multiple schemas without call populate multiple times.

For instance, we can write:

Person.find()
  .populate('address phone')
  .exec((err, results) => {
    //...
  });

This is available since version 3.6 of Mongoose.

Download and Unzip a Zip File in Memory in a Node App

We can download and unzip a zip file in memory with the adm-zip package.

To install it, we run:

npm install adm-zip

Then we can download and unzip a file as follows:

const fileUrl = 'https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v7.8.6/npp.7.8.6.bin.zip'

const AdmZip = require('adm-zip');
const http = require('http');

http.get(fileUrl, (res) => {
  let data = [];
  let dataLen = 0;

res.on('data', (chunk) => {
  data.push(chunk);
  dataLen += chunk.length;

})
.on('end', () => {
  const buf = Buffer.alloc(dataLen);

  for (let i = 0, pos = 0; i < data.length,; i++) {
    data[i].copy(buf, pos);
    pos += data[i].length;
  }

  const zip = new AdmZip(buf);
  const zipEntries = zip.getEntries();

  for (const zipEntry of zipEntries) {
    if (zipEntry.entryName.match(/readme/))
      console.log(zip.readAsText(zipEntry));
    }
  };
});

We use the http module’s get method to make a GET request to get the zip file.

Then we put the response data chunks into the data array.

Once we did that, we create a new buffer with Buffer.alloc .

Then we put the chunks in data into the buffer according to the position.

Once we copied everything into the buffer, we create a new AdmZip instance with the buffer.

Then we can get the entries from it.

We looped through the entries in the for-of loop.

Use a DOM Parser with Node.js

There are several DOM parser libraries made for Node apps.

One is the jsdom library.

We can use it by writing:

const jsdom = require("jsdom");
const dom = new jsdom.JSDOM(`<p>Hello world</p>`);
dom.window.document.querySelector("p").textContent;

We pass in an HTML string into the JSDOM constructor.

Then we can use the dom.window.document.querySelector method to get an element from the parsed DOM tree.

There’s also the htmlparser2 library.

It’s faster and more flexible than jsdom but the API is more complex.

To use it, we can write:

const htmlparser = require("htmlparser2");
const parser = new htmlparser.Parser({
  onopentag(name, attrib){
    console.log(name, attrib);
  }
}, { decodeEntities: true });
parser.write(`<p>Hello world</p>`);
parser.end();

We use the htmlparser.Parser constructor, which takes an object with the onopentag handler that’s run when the HTML string is parsed.

name has the tag name and attrib has the attributes.

decodeEntities means that we decode the entities within the document.

cheerio is another DOM parser library. It has an API similar to jQuery, so it should be familiar to many people.

We can use it by writing:

const cheerio = require('cheerio');
const $ = cheerio.load(`<p>Hello world</p>`);
$('p').text('bye');
$.html();

cheerio.load loads the HTML string into a DOM tree.

Then we can use the returned $ function to select elements and manipulate it.

Conclusion

We don’t have to create a room explicitly to join it.

We can zip files with a library.

There are many libraries to let us parse HTML strings into a DOM tree.

We can use Mongoose’spopulate to get related documents.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *