Node.js Tips — Redis, Query Strings, Concurrency of Promises, SQL Injections
Tags: node, webdev, programming, javascript
Published: 2021-01-26 03:03:10

**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.

### Best Way to Limit Concurrency when Using ES6’s Promise.all()

To limit concurrency when using `Promise.all` , we can use the `es6-promise-pool` package.

For instance, we can write:

```
const promiseProducer = function * () {
  for (let count = 1; count <= 5; count++) {
    yield delayValue(count, 1000)
  }
}

const promiseIterator = generatePromises();
const pool = new PromisePool(promiseIterator, 3);

pool.start()
  .then(function () {
    console.log('Complete')
  })
```

We get the values for the promises in the `promiseProducer` generator function.

Then we call the generator function so that we get an iterator.

We then pass that into the `PromisePool` constructor.

3 is the number of concurrent promises allowed.

Finally, we call `pool.start` to invoke the promises.

### Remove All Files from Directory without Removing Directory in Node.js

We can remove all files in a directory without removing the directory by using the `readdir` method to read the directory’s contents.

Then we can loop through each file and call `unlink` on them.

For instance, we can write:

```
const fs = require('fs');
const path = require('path');

const directory = '/foo/bar';

fs.readdir(directory, (err, files) => {
  if (err){
    return console.log(err);
  }

  for (const file of files) {
    fs.unlink(path.join(directory, file), err => {
      if (err) {
        console.log(err);
      }
    });
  }
});
```

We call `readdir` to read the directory’s content. Then we use the for-of loop to loop through the items.

Then we call `unlink` to remove each file.

### Redis and Node.js

We can access a Redis database by using the `redis` library.

To install it, we run:

```
npm install redis
```

Then in our Node app, we can use the Redis client by writing:

```
const redis = require("redis");
const client = redis.createClient();

client.on("error", (err) => {
  console.log(err);
});

client.set("key", "val", redis.print);
client.hset("hash key", "foo", "value 1", redis.print);
client.hset(["hash key", "bar", "value 2"], redis.print);
client.hkeys("hash key", (err, replies) => {
  replies.forEach((reply, i) => {
    console.log(i, reply);
  });
  client.quit();
});
```

We use the `redis` module and call `createClient` to create the client.

Then we attach a listener to listen to the `'error'` event.

Then we call `set` to set the key and value.

We can use `hset` to set a hash key with their own value.

`redis.print` prints the values.

`hkeys` get the hash keys and print the index and results.

### Parsing Query String in Node.js

We can parse the query string in Node.jhs with the `url` module.

For instance, if we’re using the `http` module to create our server, we can write:

```
const http = require('http');
const url = require('url');

const server = http.createServer((request, response) => {
  const queryData = url.parse(request.url, true).query;
  response.writeHead(200, { "Content-Type": "text/plain" });

  if (queryData.name) {
    response.end(queryData.name);
  } else {
    response.end("hello worldn");
  }
});

server.listen(8000);
```

We call `url.parse` to parse the query string that’s in the URL.

The request URL is stored in the `request.url` property.

The parsed result is assigned to the `queryData` constant.

Then we parse the `name` query parameter if it exists.

If make a request with query string `?name=joe` , then `queryData.name` will be `'joe'` .

### Preventing SQL Injection in Node.js

To prevent SQL injection in Node apps, we should use a library that lets to make parameterized queries.

For instance, with the node-mysql-native library, we can write:

```
const userId = 5;
const query = connection.query('SELECT * FROM users WHERE id = ?', [userId], (err, results) => {
  //...
});
```

The `?` indicates the parameter that we can pass in. The 2nd argument has the parameters.

The callback is called when the query is done.

`results` has the results.

Sanitization is done by the following rules:

*   numbers are untouched
*   booleans are converted to strings
*   date objects are converted to YYYY-mm-dd:ii:ss strings
*   buffers are converted to hex strings
*   strings are escaped
*   arrays are turned into lists
*   nested arrays are turned into grouped lists
*   objects are turned into `key = 'val'` pairs
*   `undefined` or `null` are converted to `NULL`
*   `NaN` and `Infinity` are left as is. They aren’t supported by MySQL and will error out if these are present.

### Conclusion

We should use a library to make database queries to prevent SQL injection.

Also, we can use a library to limit the concurrency of parallel promises.

We can use Node’s Redis library to access Redis databases.

The `url` package can parse query strings.