diff --git a/packages/quiz/questions/explain-the-difference-between-synchronous-and-asynchronous-functions/en-US.mdx b/packages/quiz/questions/explain-the-difference-between-synchronous-and-asynchronous-functions/en-US.mdx index ea53528fa..2f319af45 100644 --- a/packages/quiz/questions/explain-the-difference-between-synchronous-and-asynchronous-functions/en-US.mdx +++ b/packages/quiz/questions/explain-the-difference-between-synchronous-and-asynchronous-functions/en-US.mdx @@ -2,6 +2,163 @@ title: Explain the difference between synchronous and asynchronous functions --- +## TL;DR + Synchronous functions are blocking while asynchronous functions are not. In synchronous functions, statements complete before the next statement is run. In this case, the program is evaluated exactly in order of the statements and execution of the program is paused if one of the statements take a very long time. +```js +function sum(a, b) { + console.log('inside sum function'); + return a + b; +} + +const result = sum(2, 3); // The program waits for sum() to complete before assigning the result +console.log(result); // Output: 5 + +// Output order +// inside sum function +// 5 +``` + Asynchronous functions usually accept a callback as a parameter and execution continue on the next line immediately after the asynchronous function is invoked. The callback is only invoked when the asynchronous operation is complete and the call stack is empty. Heavy duty operations such as loading data from a web server or querying a database should be done asynchronously so that the main thread can continue executing other operations instead of blocking until that long operation to complete (in the case of browsers, the UI will freeze). + +```js +function fetchData(callback) { + setTimeout(() => { + const data = { name: 'John', age: 30 }; + callback(data); // Calling the callback function with data + }, 2000); // Simulating a 2-second delay +} + +fetchData((data) => { + console.log(data); // Output: { name: 'John', age: 30 } (after 2 seconds) +}); + +console.log('This will be printed first'); // Output: This will be printed first + +// Output order +// This will be printed first +// { name: 'John', age: 30 } +``` + +--- + +## Synchronous vs asynchronous functions + +In JavaScript, the concepts of synchronous and asynchronous functions are fundamental to understanding how code execution is managed, particularly in the context of handling operations like I/O tasks, API calls, and other time-consuming processes. + +### Synchronous functions + +Synchronous functions execute in a sequential order, one after the other. Each operation must wait for the previous one to complete before moving on to the next. + + - Synchronous code is blocking, meaning the program execution halts until the current operation finishes. + - It follows a strict sequence, executing instructions line by line. + - Synchronous functions are easier to understand and debug since the flow is predictable. + +#### Synchronous function examples + +1. **Reading files synchronously**: When reading a file from the file system using the synchronous readFileSync method from the fs module in Node.js, the program execution is blocked until the entire file is read. This can cause performance issues, especially for large files or when reading multiple files sequentially + + ```js + const fs = require('fs'); + const data = fs.readFileSync('large-file.txt', 'utf8'); + console.log(data); // Execution is blocked until the file is read + console.log('End of the program'); + ``` + +2. **Looping over large datasets**: Iterating over a large array or dataset synchronously can freeze the user interface or browser tab until the operation completes, leading to an unresponsive application. + + ```js + const largeArray = new Array(1000000).fill(0); + const result = largeArray.map((num) => num * 2); // Blocks the main thread + console.log(result); + ``` + +### Asynchronous functions + +Asynchronous functions do not block the execution of the program. They allow other operations to continue while waiting for a response or completion of a time-consuming task. + + - Asynchronous code is non-blocking, allowing the program to keep running without waiting for a specific operation to finish. + - It enables concurrent execution, improving performance and responsiveness. + - Asynchronous functions are commonly used for tasks like network requests, file I/O, and timers. + +#### Asynchronous function examples + +1. **Network requests**: Making network requests, such as fetching data from an API or sending data to a server, is typically done asynchronously. This allows the application to remain responsive while waiting for the response, preventing the user interface from freezing + + ```js + console.log('Start of the program'); // This will be printed first as program starts here + + fetch('https://api.example.com/data') + .then((response) => response.json()) + .then((data) => { + console.log(data); + /** Process the data without blocking the main thread + * and printed at the end if fetch call succeeds + */ + }) + .catch((error) => console.error(error)); + + console.log('End of program'); // This will be printed next before the fetch callback + ``` + +2. **User Input and Events**: Handling user input events, such as clicks, key presses, or mouse movements, is inherently asynchronous. The application needs to respond to these events without blocking the main thread, ensuring a smooth user experience. + + ```js + const button = document.getElementById('myButton'); + button.addEventListener('click', () => { + // Handle the click event asynchronously + console.log('Button clicked'); + }); + ``` + +3. **Timers and Animations**: Timers (setTimeout, setInterval) and animations (e.g., requestAnimationFrame) are asynchronous operations that allow the application to schedule tasks or update animations without blocking the main thread. + + ```js + setTimeout(() => { + console.log('This message is delayed by 2 seconds'); + }, 2000); + + const animationId = requestAnimationFrame(updateAnimation); + ``` + +By using asynchronous functions and operations, JavaScript can handle time-consuming tasks without freezing the user interface or blocking the main thread. + +It is important to note that **`async` function do not run on different thread**. They still run on `main thread. However, it is possible to achieve parallelism in Javascript by using [Web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) + +### Achieving parallelism in JavaScript via Web worker + +Web Workers allow you to spawn separate background threads that can perform CPU-intensive tasks in parallel with the main thread. These worker threads can communicate with the main thread via message passing, but they do not have direct access to the DOM or other browser APIs. + +```js +// main.js +const worker = new Worker('worker.js'); + +worker.onmessage = function (event) { + console.log('Result from worker:', event.data); +}; + +worker.postMessage('Start computation'); +``` + +```js// worker.js +self.onmessage = function(event) { + const result = performHeavyComputation(); + self.postMessage(result); +}; + +function performHeavyComputation() { + // CPU-intensive computation + return 'Computation result'; +} +``` + +In this example, the main thread creates a new Web Worker and sends it a message to start a computation. The worker performs the heavy computation in parallel with the main thread and sends the result back via postMessage. + +## Further reading + +- [Asynchronous javaScript](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous) +- [The Basics: synchronous and asynchronous JavaScript](https://www.linkedin.com/pulse/basics-synchronous-asynchronous-javascript-abdulkabir-okeowo) +- [Synchronous and asynchronous programming in JavaScript](https://code.pieces.app/blog/synchronous-and-asynchronous-programming-in-javascript) +- [Web Workers API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) +- [An overview of web workers - Web.dev](https://web.dev/learn/performance/web-worker-overview)