In Node.js, callbacks are a common pattern used to handle asynchronous operations. All the Nodejs API is written in such a way, that it supports callbacks.
As Node.js is designed to be non-blocking and event-driven, many of its APIs use callbacks to execute code once the task is completed.
Callbacks are functions passed as arguments to other functions, and they are executed after the completion of a specific task.
Error first Approach using Callback functions can handle errors by passing an error object as the first argument. This convention allows us to propagate and handle errors effectively in asynchronous code.
Here are some examples of Callback functions in Node.js:
In the below example, we have a `calculator` function that accepts 3 arguments, two arguments as `integer values` and one `callback` function. The `calculator` function will return us an object of keys such as `sum` and `multiply` with values.
function calculateMultiply(a, b) { return a * b; } function calculator(a, b, callbackFunction) { return { sum: a + b, multiply: callbackFunction(a, b), }; } const response = calculator(3, 5, calculateMultiply); console.log("Result: ", response);
when the `calculator` function is invoked it will store the response of `a + b` operation value in the `sum` key and then move to the next line, where we have the function named `callbackFunction` It is the same function, what we pass in the `calculator` but the name of the function we have changed. so it will invoke the `calculateMultiply` function and store its response value in the `multiply` key.
Result: { sum: 8, multiply: 15 }
Many Node.js functions follow the pattern of accepting a callback as the last argument. We can also create custom functions that utilize callbacks:
function fetchData(url, callback) { // Simulating an asynchronous operation (e.g., fetching data from a database) setTimeout(() => { const data = fetch(url).then((res) => res.json()) callback(null, data); // Pass null for error, and the data }, 1000); } // Calling fetchData function fetchData("https://www.example.com/comment", (err, result) => { if (err) { console.error("Error:", err.message); return; } console.log("Result:", result); });
Callbacks often include error handling to handle potential issues that may occur during an asynchronous operation:
function divideAsync(a, b, callback) { if (b == 0) { // Handle division by zero error const error = new Error("Division by zero"); callback(error); return; } const result = a / b; callback(null, result); } // Calling divideAsync function divideAsync(40, 0, (err, result) => { if (err) { console.error("Error:", err.message); return; } console.log("Result:", result); });
Here, the `divideAsync` function checks for a division by zero scenario and invokes the callback function if encountered error.
In the `divideAsync` function we have passed the 2nd argument value as `0`. If the code entered in the condition where `b == 0` we were checking then it will throw an error in the `callback` function.
Error: Division by zero