How to make fs.readFile async await?
To use await
, you need to use promise versions of fs.readFile()
and fs.readdir()
which you can get on fs.promises
and if you want these to run sequentially, then use a for
loop instead of .map()
:
async function readingDirectory(directory) {
const fileNames = await fs.promises.readdir(directory);
for (let file of fileNames) {
const absolutePath = path.join(directory, file);
log(absolutePath);
const data = await fs.promises.readFile(absolutePath);
log(data);
}
}
readingDirectory(folder).then(() => {
log("all done");
}).catch(err => {
log(err);
});
How to read file with async/await properly?
To use await
/async
you need methods that return promises. The core API functions don't do that without wrappers like promisify
:
const fs = require('fs');
const util = require('util');
// Convert fs.readFile into Promise version of same
const readFile = util.promisify(fs.readFile);
function getStuff() {
return readFile('test');
}
// Can't use `await` outside of an async function so you need to chain
// with then()
getStuff().then(data => {
console.log(data);
})
As a note, readFileSync
does not take a callback, it returns the data or throws an exception. You're not getting the value you want because that function you supply is ignored and you're not capturing the actual return value. How to use async/await with file system module
You can "promisefy" all callback style functions!
// promisefy this:
fs.unlink('path/file.txt', (err) => {
if (err) throw err;
console.log('path/file.txt was deleted');
});
// to this:
const unlinkPromise = (path) => new Promise((resolve, reject) => {
fs.unlink('path/file.txt', (err) => {
if (err) reject(err);
resolve(path);
});
});
// and then call with await or chain promises
await unlinkPromise('path/file.txt').then((path) => {
console.log(`${path} was deleted`);
});
But as already mentioned, the sync method does not require await, this strategy, I would recommend for promise cascades... Node.js read file using async/await
There are many ways to achieve that.
Most of them is explained in this link
I'll write simple one:
1) using util.promisify
to convert callback method to promise:
const fs = require('fs');
const util = require('util');
const readFile = (fileName) => util.promisify(fs.readFile)(fileName, 'utf8');
(async () => {
try {
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
for (const file of files) {
console.log(
await readFile(file)
);
}
}
catch (error) {
console.error(error);
}
})();
2) *Sync
methods. Since Your code is not dealing with concurrency You can use *Sync
methods:const fs = require('fs');
try {
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
for (const file of files) {
console.log(
fs.readFileSync(file, 'utf8')
);
}
}
catch (error) {
console.error(error);
}
BTW. Here is Your fixed code:
var fs = require('fs');
function readFile(fileName) {
return new Promise((resolve, reject) => {
fs.readFile(fileName, 'utf8', function (error, data) {
if (error) return reject(error);
console.log(fileName)
console.log(data)
resolve();
})
});
}
async function run() {
await readFile('file1.txt');
await readFile('file2.txt');
await readFile('file3.txt');
}
run();
since You're calling readFile and resolve at same async sequence it's being called at same time which is reason of race condition
.You've to wait for callback handling and then resolve it (inside callback scope).
readFile async await in nodejs
The readFile()
is non-blocking so you're calling res.end()
BEFORE you call res.write()
. I'd suggest using await
like this:
const server = http.createServer(async (req, res) => {
if(req.url === `/`){
try {
const data = await readDemo(`./todo.html`);
res.writeHead(200,{"Content-type":"text/html"});
res.write(data)
res.end();
} catch(e) {
console.log(e);
res.writeHead(500);
res.end();
}
} else {
res.writeHead(404);
res.end();
}
});
Without await
, you need to move the res.end()
inside of the .then()
:const server = http.createServer((req,res)=>{
if(req.url === `/`){
readDemo(`./todo.html`).then(data => {
res.writeHead(200,{"Content-type":"text/html"});
res.write(data);
res.end();
}).catch(err => {
console.log(err);
res.writeHead(500);
res.end();
});
} else {
res.writeHead(404);
res.end();
}
});
FYI, in modern versions of node.js fs.promises.readFile()
is already a promise version so you don't have to make your own. Is it ever better to use Node's filesystem sync methods over the same async methods?
It depends on the situation. The main benefit of the sync methods is that they allow for easier consumption of their results, and the main disadvantage is that they prevent all other code from executing while working.
If you find yourself in a situation where other code not being able to respond to events is not an issue, you might consider it to be reasonable to use the sync methods - if the code in question has no chance of or reason for running in parallel with anything else.
For example, you would definitely not want to use the sync methods inside, say, a server handling a request.
If your code requires reading some configuration files (or creating some folders) when the script first runs, and there aren't enough of them such that parallelism would be a benefit, you can consider using the sync methods.
That said, even if your current implementation doesn't require parallelism, something to keep in mind is that, if the situation changes and you find that you do actually need to allow for parallel processing, you won't have to make any changes to your existing code if you had started out by using the promise-based methods in the first place - and if you understand the language, using the Promises properly should be pretty easy, so if there's a chance of that, you might consider using the Promises anyway.
Related Topics
I Can't Reference an Image in Next.Js
Intercept Paste Event in JavaScript
JavaScript Getelementbyname Doesn't Work
How to Trigger Click on Page Load
Why Does a Simple .*? Non-Greedy Regex Greedily Include Additional Characters Before a Match
Understanding JavaScript Immutable Variable
Angularjs - Cancel Route Change Event
Angularjs Communication Between Directives
Why Are Await and Async Valid Variable Names
Get Selected HTML in Browser via JavaScript
Parse String to Date with Moment.Js
Should Github Be Used as a Cdn for JavaScript Libraries
How to Randomly Generate HTML Hex Color Codes Using JavaScript
Create Copy of Multi-Dimensional Array, Not Reference - JavaScript
How to Parse a Date in Format "Yyyymmdd" in JavaScript
Typeerror: $ Is Not a Function Wordpress
Create an Array with Random Values
How to Use Promise in Foreach Loop of Array to Populate an Object