Using Q and Promises to Read from File with Node
Project Files
Click here to download the project files.
...
Also be sure to check out my latest course on Angular 2 using this coupon link: http://bit.ly/1SWkFxM
Using q
is very easy. In this post we are going to use the defer
method to create a deferred
object which represents a value that will be resolved or rejected in the future. For example, when we read from file with Node asynchronously, if the operation is successful, then you can resolve the object with the content of the file, otherwise you can reject it and catch it in your code. Let's gat started.
Make a folder on your desktop, navigate to it and start a package.json
file and accept all the defaults:
mkdir ~/Desktop/q-read && cd $_ && npm init
Install q
:
npm i q -S # -S means as a production dependency
Make a dummy file:
touch dummy.txt
echo hello > dummy.txt
Make the main.js
file that will contain the main code:
touch main.js
Now we are ready to fill the main.js
file.
First, let's just read the file with vanilla Node:
var fs = require('fs');
fs.readFile('./dummy.txt', 'utf-8', function (err, data) {
if (err) {return console.log(err);}
console.log(data);
});
Here we are just reading the content of the dummy.txt
file in utf-8
format, and just logging the content to the console. If you run the code with node main.js
, you should get the following output:
> node main.js
hello
Now, let's make things interesting. We are going to create a function called read
that returns a promise:
var q = require('q');
var read = function () {
var deferred = q.defer();
deferred.resolve('done');
return deferred.promise;
};
If you look at the code, first we load q
. Then, we create a function and in the function we first create a deferred
object. And we just resolve it with a dummy value called 'done'. And at the end we return the promise
property of deferred
.
Now, let's see how we can use the read
function. So, obviously we are going to call the function first:
read()
When we call read
it will return a promise. The promise has a method called then
which can be used to access the resolved value:
read().then();
Now the then
method takes a function, and the resolved value will be passed to the function as a parameter:
read().then(function doSomething(resolvedData) {});
And inside the function we can do whatever we want with the data:
read().then(function doSomething(resolvedData) {
console.log(resolvedData);
});
This will log done
to the console, because that is the value that we resolved. Now let's see how we can apply the same principle to the fs.readFile
method.
var fs = require('fs');
var q = require('q');
var read = function () {
var deferred = q.defer();
fs.readFile('./dummy.txt', 'utf-8', function (err, data) {
if (err) {deferred.reject(err)}
else { deferred.resolve(data) }
});
return deferred.promise;
};
read().then(function (content) {
console.log(content);
}).catch(function (err) {
console.log(err);
}).finally(function () {
console.log('Read is done.');
});
If you look at the code, you can see that we are using the same principle. There are a couple of new things, so let's go over them.
In the body of the function, we check for error, if an error happens we reject
the promise with the err
. Otherwise, we resolved the promise with the content of the file. Now, when we call the read function, we can grab the resolved value in the then
block. But if there is an error, we will catch that in the catch
block. And at the end, regardless of what happened, we will log to the console in the finally
block.
And that's it! As an exercise, you can try implementing the fs.writeFile
method as well, the principles are the same.