From callbacks to fs/promises to handle the file system in Node.js
Tags: node, javascript, filesystem
Published: 2018-05-25 06:34:49

---
title: From callbacks to fs/promises to handle the file system in Node.js
published: true
description: In this post we are going to see the evolution of Node.js to work with the file system.
tags: node, javascript, filesystem
---

In this post, I will show you the evolution of Node.js to work with the file system.
Let's start by creating a file:

```js
const fs = require("fs");

fs.writeFile("/tmp/test.js", "console.log('Hello world');", error => {
    if (error) console.error(error);
    else console.log("file created successfully!");
});
```
If we wanted to avoid **callbacks**, before *Node.js v8* we had to manually promisify the **fs.writeFile** function or using third party modules such as **bluebird** or **Q**.

Let's promisify manually and wrap in a function the above code:

```js
const fs = require("fs");

const writeFilePromise = (file, data) => {
    return new Promise((resolve, reject) => {
        fs.writeFile(file, data, error => {
            if (error) reject(error);
            resolve("file created successfully with handcrafted Promise!");
        });
    });
};

writeFilePromise(
        "/tmp/test2.js",
        "console.log('Hello world with handcrafted promise!');"
    )
    .then(result => console.log(result))

    .catch(error => console.log(error));
```
With the arrival of *Node.js V8*, **'util.promisify()'** alllowed us to convert I/O functions that return callbacks into I/O functions that return promises.

```js
const fs = require("fs");
const util = require("util");

const writeFile = util.promisify(fs.writeFile);

writeFile("/tmp/test3.js", "console.log('Hello world with promisify!');")
  .then(() => console.log("file created successfully with promisify!"))

  .catch(error => console.log(error));
```
Let's see the **async/await** version:

```js
const fs = require("fs");
const { promisify } = require("util");

const writeFile = promisify(fs.writeFile);

async function main() {
    await writeFile("/tmp/test4.js",
        "console.log('Hello world with promisify and async/await!');");

    console.info("file created successfully with promisify and async/await!");
}

main().catch(error => console.error(error));
```
In its latest release (*Node.js V10*), functions of the **fs** can return promises directly, eliminating the extra step and overhead of the old way. This due to its **fs/promises** API.

```js
const fsp = require("fs/promises");

try {
    await fsp.writeFile("/tmp/test5.js", "console.log('Hello world with Node.js v10 fs/promises!'");
    console.info("File created successfully with Node.js v10 fs/promises!");
} catch (error){
    console.error(error);
}
```
Note I am using **top level await** (my *await* code is not inside and *async* function). This feature is experimental yet, so if you want to check it out, use the following flag: *-- experimental-repl-await*.

The **fs/promises** API provides the following methods:

>  access, copyFile, open, read, write, rename, truncate, ftruncate, rmdir, fdatasync, fsync, mkdir, readdir, readlink, symlink, fstat, lstat, stat, link, unlink, fchmod, chmod, lchmod, lchown, fchown, chown, utimes, futimes, realpath, mkdtemp, writeFile, appendFile and readFile.

Update:

In *Node 13* it works even with *ESM modules*:
```js
import { promises as fs } from 'fs';

try {
    await fs.writeFile("/tmp/test6.js", "console.log('Hello world with Node.js v13 fs.promises!'");
    console.info("File created successfully with Node.js v13 fs.promises!");
} catch (error){
    console.error(error);
}
```