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
ornull
are converted toNULL
-
NaN
andInfinity
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.