Asynchronous code is an important concept in Node.js. It allows the program to run non-blocking code, which means that other operations can be performed while waiting for a task to complete.
Callbacks are a traditional way of handling asynchronous code in Node.js. A callback function is passed as an argument to a function that performs an asynchronous operation. When the operation is complete, the callback function is executed.
fs.readFile('file.txt', (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data)
})
In the example above, the readFile
function reads the contents of file.txt
. When the file is read, the callback function is executed. If an error occurs during the operation, the error is passed to the callback function as the first argument.
Promises provide a cleaner way of handling asynchronous code in Node.js. Promises represent a value that may not be available yet and allow you to chain multiple asynchronous operations together.
const fs = require('fs/promises')
fs.readFile('file.txt')
.then(data => {
console.log(data)
})
.catch(err => {
console.error(err)
})
In the example above, the readFile
function returns a promise. When the promise is resolved, the then
function is executed. If the promise is rejected, the catch
function is executed.
Async/await is a newer way of handling asynchronous code in Node.js. It provides a more readable and concise way of writing asynchronous code by using the async
and await
keywords.
const fs = require('fs/promises')
async function readFile() {
try {
const data = await fs.readFile('file.txt')
console.log(data)
} catch (err) {
console.error(err)
}
}
readFile()
In the example above, the readFile
function is marked as async
. This allows us to use the await
keyword to wait for the readFile
function to complete before executing the next line of code. If an error occurs during the operation, it is caught by the try/catch
block.
Error handling is an important part of handling asynchronous code in Node.js. In all of the examples above, error handling is performed using a try/catch
block or a catch
function.
It's important to handle errors properly to avoid crashing the application. In addition, it's important to provide meaningful error messages to help with debugging.