Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,45 +115,63 @@ threads may be created to handle concurrent work.

## Dangers of Mixing Blocking and Non-Blocking Code

There are some patterns that should be avoided when dealing with I/O. Let's look
at an example:
There are some patterns that should be avoided when dealing with I/O. Let's look at an example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change


```js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example change isn't what we want.

We want:

operationWithCallback(() => { ... })
operationWithoutCallback()

const fs = require('node:fs');

fs.readFile('/file.md', (err, data) => {
if (err) {
throw err;
const path = require('node:path');

// Create and use a temporary file
const tempFile = path.join(__dirname, 'temp.md');
try {
fs.writeFileSync(tempFile, 'Temporary content');

// Perform blocking delete first
fs.unlinkSync(tempFile);

// Attempt asynchronous read afterward
fs.readFile(tempFile, (err, data) => {
if (err) {
console.log('Error: Read failed with', err.code, 'as expected due to prior deletion.');
} else {
console.log('Unexpected success:', data.toString());
}
});
// Note: The callback may not log immediately; the process exits before I/O completes.
} finally {
// Cleanup (though file is already deleted)
if (fs.existsSync(tempFile)) {
fs.unlinkSync(tempFile);
}

console.log(data);
});
fs.unlinkSync('/file.md');
}
```

In the above example, `fs.unlinkSync()` is likely to be run before
`fs.readFile()`, which would delete `file.md` before it is actually read. A
better way to write this, which is completely **non-blocking** and guaranteed to
execute in the correct order is:
In the above example, fs.unlinkSync() is run before the asynchronous fs.readFile() operation, which deletes temp.md before the read can occur. This results in a failure (e.g., ENOENT error), demonstrating the danger of mixing blocking and non-blocking calls without proper sequencing. The try-finally block ensures the file is managed, though the read failure is the key lesson here. To avoid such issues, ensure operations are ordered correctly...


>**Note**: Due to the asynchronous nature of `fs.readFile`, the `console.log` may not execute immediately. You might need to add a `setTimeout` or keep the process alive (e.g., with `process.stdin.resume()`) to see the output.

```js
const fs = require('node:fs');
const path = require('node:path');

const tempFile = path.join(__dirname, 'temp.md');
fs.writeFileSync(tempFile, 'Temporary content');

fs.readFile('/file.md', (readFileErr, data) => {
fs.readFile(tempFile, (readFileErr, data) => {
if (readFileErr) {
throw readFileErr;
}

console.log(data);

fs.unlink('/file.md', unlinkErr => {
fs.unlink(tempFile, unlinkErr => {
if (unlinkErr) {
throw unlinkErr;
}
});
});
```

The above places a **non-blocking** call to `fs.unlink()` within the callback of
`fs.readFile()` which guarantees the correct order of operations.

Expand Down