Home > OS >  Understanding node.js require('fs') vs require('fs').promises;
Understanding node.js require('fs') vs require('fs').promises;

Time:11-21

I have two methods.

The first one reads a file and writes to that file just as plain text. The second one writes a file as a stream.

In order to get this to work I have had to add fs twice in require.

const fs = require('fs').promises;
const fs2 = require('fs');

I'm trying to understand the difference and why I need this twice. But it sems that fs with out the promise doesn't have the ability to use createWriteStream and the one without the .promises doesnt have the ability to writeFile

/**
 * Serializes credentials to a file compatible with GoogleAUth.fromJSON.
 *
 * @param {OAuth2Client} client
 * @return {Promise<void>}
 */
async function saveCredentials(client) {
    const content = await fs.readFile(CREDENTIALS_PATH);
    const keys = JSON.parse(content);
    const key = keys.installed || keys.web;
    const payload = JSON.stringify({
        type: 'authorized_user',
        client_id: key.client_id,
        client_secret: key.client_secret,
        refresh_token: client.credentials.refresh_token,
    });
    await fs.writeFile(TOKEN_PATH, payload);
}

The second one writes to a file as a stream

/**
 * Download file
 * @param {OAuth2Client} authClient An authorized OAuth2 client.
 */
async function downloadFile(authClient) {

    const service = google.drive({version: 'v3', auth: authClient});
    const fileStream = fs2.createWriteStream("test.txt")
    fileId = FILEID;
    try {
        const file = await service.files.get({
            fileId: fileId,
            alt: 'media',
        }, {
                responseType: "stream"
            },
            (err, { data }) =>
                data
                    .on('end', () => console.log('onCompleted'))
                    .on('error', (err) => console.log('onError', err))
                    .pipe(fileStream)
        );
    } catch (err) {
        // TODO(developer) - Handle error
        throw err;
    }
}

Note this does work, I am just trying to wrap my head around Node.js.

CodePudding user response:

fs.promises contains a subset of the interface for what's on fs, but with promise-based interfaces instead of plain callback-style interfaces.

Some things which don't translate well to promises or don't have a natural promise-based interface such as fs.createReadStream() are only available on fs. Note that fs.createReadStream() returns a stream and uses events on the stream, not plain callbacks (which don't translate well to promises). As such, it's interface remains the same on fs and is not duplicated on fs.promises.

Many things are available in either with different interfaces:

fs.writeFile(filename, data, callback);     // plain callback interface

or

await fs.promises.writeFile(filename, data)    // promise interface

Most of the time, I can use only the fs.promises interface and do:

const fsp = require('fs').promises;

But sometimes, you need both and I would do this:

const fs = require('fs');
const fsp = fs.promises;

Keep in mind fs.promises is not a complete replacement for fs. It's an alternate (promise-based) interface for some (but not all) of the methods in the fs module.

Other interfaces such as fsp.open() have been enhanced and converted to promises in the fs.promises interface where it now returns a promise that resolves to an object-oriented fileHandle object whereas fs.open() just accepts a callback that will be passed a file descriptor.


So, my mode of operation is to look in the fs.promises interface for what I'm doing. If it's there, I use it there and use promises with it.

If it's not there, then go back to the fs interface for what I need.


I would advise you to NOT write code that uses the symbol fs for fs.promises. That will confuse people reading or working on your code because they are likely to think that a symbol named fs is the fs interface. That's why I use fs for the fs interface and fsp for the fs.promises interface in my code.

  • Related