简体   繁体   中英

Questions regarding fs in node.js

Objective

To know when fs.writeFileSync() or fs.writeFile() are done writing a file, so I can execute another function.

Background

I am writing a file using fs and in order to know when the file is done writing, I checked its documentation:

After reading it, I focused my attention in both fs.writeFile() and fs.writeFileSync() but I find the documentation lacking and I have doubts.

Questions about fs.writeFile()

  1. Is the callback function called before the file is written, as it is being written or after it was written and saved in disk?

Questions about fs.writeFileSync()

  1. How do I know if an error occurred if it always returns undefined ?
  2. Being a synchronous write, does it mean that my code will be forced to wait until the file is fully written ?

General questions

  1. If I wanted to write two different files at the same time, and to perform a single action when both are complete, how would I do it using fs.writeFile() ?
  2. Is there any user-friendly library in NPM for doing this kind of work? I searched but I didn't find anything convincing.

Conclusion

I am overall confused with fs and my knowledge is not enough to maximize its usage in my code. To improve, I need to see more code samples, so answers with code samples will be preferred.


Thank you for your time !

First off, here's a big tip. If the documentation does not explain something and you can't easily answer the question with a simple test, then you can always just go look at the source on GitHub. For example, here's the source for fs.writeFileSync() on Github . This is one of the massive advantages of open source projects. When in doubt, just go look at the code.

Sometimes, its not so easy to find the right source code (GitHub search tends to find 10x more hits in test case code than in the original source). In those cases, you can just set a breakpoint in your own code in the debugger and step right into the function in question. The debugger will take you right to the source and you can see exactly what it is doing.

Now for your questions...

Questions about fs.writeFile()

Is the callback function called before the file is written, as it is being written or after it was written and saved in disk?

It is called after the file has been written (or when an error was encountered).

Questions about fs.writeFileSync()

  1. How do I know if an error occurred if it always returns undefined?

fs.writeFileSync throws exceptions if there are errors. You must use try/catch to catch any exceptions.

  1. Being a synchronous write, does it mean that my code will be forced to wait until the file is fully written ?

Yes, the synchronous version will block until the file is fully written. You would not use the synchronous version in normal server development because it would tie up the main node.js thread.

General questions

If I wanted to write two different files at the same time, and to perform a single action when both are complete, how would I do it using fs.writeFile()?

The typical design pattern for this type of problem these days using promises and Promise.all() to track the completion of multiple asynchronous operations.

Using the Bluebird promise library:

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));

Promise.all([fs.writeFileAsync(fname1, data1), fs.writeFileAsync(fname2, data2)]).then(function() {
    // both async operations are done here
}).catch(function(err) {
    // handle error here
});

Bluebird's .promisifyAll() method wraps each async operation in the fs module with a function returning a promise and names that wrapped version with an Async suffix so fs.writeFile() gets fs.writeFileAsync() that returns a promise instead of taking a direct callback. You can then use Promise control flow such as Promise.all() to manage or coordinate multiple async operations.

You don't have to use the Bluebird library for this since Promises are built into node.js now (and part of the ES6 specification), but node.js doesn't have as easy a way to turn existing async callback functions into promise returning functions and Bluebird does. You could do the promisification yourself if you wanted.

const fs = require('fs');

fs.writeFileAsync = function(fname, data) {
    return new Promise(function(resolve, reject) {
        fs.writeFile(fname, data, function(err) {
            if (err) return reject(err);
            resolve();
        });
    });
}

Promise.all([fs.writeFileAsync(fname1, data1), fs.writeFileAsync(fname2, data2)]).then(function() {
    // both async operations are done here
}).catch(function(err) {
    // handle error here
});

So many questions... let's go:

( fs.writeFile() ...) Is the callback function called before the file is written, as it is being written or after it was written and saved in disk?

After the operation is done, whether successful or not.

( fs.writeFileSync() ...) How do I know if an error occurred if it always returns undefined ?

It will throw an exception .

Being a synchronous write, does it mean that my code will be forced to wait until the file is fully written?

Yes! that's the point of a synchronous function.


If I wanted to write two different files at the same time, and to perform a single action when both are complete, how would I do it using fs.writeFile() ?

Here's one way:

const fs = require('fs');

let completions = 0;

function onComplete(err) {
  if(err) {
    console.log('An error occurred', err);
  }

  completions++;
  if(completions === 2) {
    console.log('All done!');
  }
}

fs.writeFile('file1.txt', 'Hello', onComplete);
fs.writeFile('file2.txt', 'World', onComplete);

Is there any user-friendly library in NPM for doing this kind of work? I searched but I didn't find anything convincing.

Not exactly (that I know of...), but you should be looking at using promises and promisified fs calls. Then you'll be able to use Promise.all and it'll all look much nicer!

Is the fs.writeFile() callback function called before the file is written, as it is being written or after it was written and saved in disk?

The function is called when the file has finished writing to disk.

How do I know if an error occurred in fs.writeFileSync() if it always returns undefined ?

> fs.writeFileSync('/test', 'foo')
Error: EACCES: permission denied, open '/test'
    at Error (native)
    ...

It'll throw an error which you can try..catch .

fs.writeFileSync() being a synchronous write, does it mean that my code will be forced to wait until the file is fully written ?

Yes; as with all synchronous functions, your code will block until the function returns.

If I wanted to write two different files at the same time, and to perform a single action when both are complete, how would I do it using fs.writeFile() ?

Use promises :

let write1 = new Promise((resolve, reject) => {
    fs.writeFile(file1, data1, err => {
        if (err) {
            reject(err);
        } else {
            resolve();
        }
    });
});

let write2 = new Promise(/* same thing here */);

Promise.all([write1, write2]).then(() => {
    console.log('both writes done');
});

fs.writeFile() is asynchronous. this means the callback happens after the file is written to. fs.writeFileSync() is not, meaning it is non-blocking and other proceeding code will be executed. To write to two separate files, and do something once they are both done, you would simply nest the aysnc callbacks like

fs.writeFile('test.txt', 'text', function(){
    fs.writeFile('test2.txt', 'text', function(){
        console.log('done');
    });
});

To know there is an error in sync functions, you would use an exception.

Here's what you are looking for :

Q1)Is the callback function called before the file is written, as it is being written or after it was written and saved in disk?

Ans1) Callback function returns the error or success after the write file operation is attempted. In attempt either it fails or writes successfully. So it would return error, success in callback. So finally, callback is called after "write file operation is attempted".

Q2)How do I know if an error occurred if it always returns undefined?

Ans2) You can use try and catch because if it writes successfully then return no response but if it fails in doing so. You'll get an exception.

Q3)Being a synchronous write, does it mean that my code will be forced to wait until the file is fully written ?

Ans3)Yes, being synchronous in nature don't let other statements/operation executes until whole file writing task has been written.

Q4)If I wanted to write two different files at the same time, and to perform a single action when both are complete, how would I do it using fs.writeFile()?

Ans4) So, in this case you can use callbacks or promise. In simple terms you can you can chain the tasks one after other if they are dependent over each other . But if they are independent of each other just simple write two blocks of code writing. It would write easily. Below given code is for two independent task.

fs.writeFile('file.txt', 'hello', function(error){ //do something }); fs.writeFile('file1.txt', 'Amulya', function(error){ //do something});

they'll both execute at sametime because async nature and they would complete without any hassle.

Q5) Is there any user-friendly library in NPM for doing this kind of work? I searched but I didn't find anything convincing.

Ans5) No NPM library is needed indeed if bopth task are independent of each other as in above example. If they dependent over each other means then you can use async or bluebird to chain or promisify them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM