Skip to content

Commit c456f08

Browse files
authored
callbacks
1 parent 93c2344 commit c456f08

1 file changed

Lines changed: 158 additions & 2 deletions

File tree

JavaScript/functions.md

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ const obj = {
143143
}
144144
145145
obj.getName(); // "Krishna" this refers to obj which called the method.
146-
obj.getArrowName(); //undefined
146+
obj.getArrowName(); //undefined this refers to global object.
147147
```
148148
#### 3. Constructor Function
149149
When a function is used as a constructor with the new keyword, this refers to the newly created object instance.
@@ -295,7 +295,163 @@ async function processUserData() {
295295
processUserData();
296296
```
297297

298-
## Closure?
298+
299+
**1. Callbacks**
300+
301+
* **What they are:** A callback is a function that is passed as an argument to another function and is executed *after* the first function completes its task. They are the traditional way to handle asynchronous operations in JavaScript.
302+
303+
* **Why they're used:** JavaScript is single-threaded and non-blocking. This means that long-running operations (like network requests or file I/O) shouldn't halt the execution of the rest of your code. Callbacks allow you to start an operation and then specify what should happen once it's finished, without blocking the main thread.
304+
305+
* **Example:**
306+
307+
```javascript
308+
function fetchData(url, callback) {
309+
// Simulate an asynchronous operation (like fetching data from an API)
310+
setTimeout(() => {
311+
const data = { name: "John Doe", age: 30 }; // Sample data
312+
callback(data); // Call the callback function with the data
313+
}, 1000); // Simulate a 1-second delay
314+
}
315+
316+
function processData(data) {
317+
console.log("Data received:", data);
318+
// Perform some operations on the received data
319+
console.log("Name:", data.name);
320+
console.log("Age:", data.age);
321+
}
322+
323+
fetchData("some_url", processData); // Pass processData as the callback
324+
325+
console.log("Fetching data..."); // This will execute *before* the data is fetched
326+
327+
// Output:
328+
// Fetching data...
329+
// Data received: { name: 'John Doe', age: 30 }
330+
// Name: John Doe
331+
// Age: 30
332+
```
333+
334+
* **Explanation:** `fetchData` simulates an asynchronous operation. `processData` is the callback. Notice how "Fetching data..." logs *before* the data is actually received. This demonstrates the non-blocking nature of asynchronous JavaScript. Once the `setTimeout` finishes (after 1 second), it calls the `processData` function, passing the retrieved data.
335+
336+
* **Callback Hell (Pyramid of Doom):** A major drawback of callbacks is that nested asynchronous operations can lead to complex and hard-to-read code, often called "callback hell" or the "pyramid of doom."
337+
338+
```javascript
339+
// Example of nested callbacks (callback hell)
340+
getData1((data1) => {
341+
getData2(data1, (data2) => {
342+
getData3(data2, (data3) => {
343+
// ... more nested callbacks ...
344+
});
345+
});
346+
});
347+
```
348+
349+
**2. Promises**
350+
351+
* **What they are:** Promises are a cleaner way to handle asynchronous operations. A Promise represents the eventual result of an asynchronous operation. It can be in one of three states:
352+
* *Pending:* The initial state, before the operation completes.
353+
* *Fulfilled (Resolved):* The operation completed successfully.
354+
* *Rejected:* The operation failed.
355+
356+
* **Why they're used:** Promises make asynchronous code more readable and manageable, avoiding the problems of callback hell. They provide a more structured way to handle asynchronous results and errors.
357+
358+
* **Example:**
359+
360+
```javascript
361+
function fetchDataPromise(url) {
362+
return new Promise((resolve, reject) => {
363+
setTimeout(() => {
364+
const data = { name: "Jane Doe", age: 25 };
365+
// Simulate success:
366+
resolve(data);
367+
368+
// Simulate an error:
369+
// reject("Error fetching data");
370+
}, 1000);
371+
});
372+
}
373+
374+
fetchDataPromise("some_url")
375+
.then((data) => {
376+
console.log("Data received:", data);
377+
console.log("Name:", data.name);
378+
console.log("Age:", data.age);
379+
return data; // You can chain promises
380+
})
381+
.then((data) => { // Example of chaining
382+
console.log("Data processed further:", data.age * 2);
383+
})
384+
.catch((error) => {
385+
console.error("Error:", error);
386+
});
387+
388+
console.log("Fetching data with Promise..."); // This executes first
389+
390+
// Output:
391+
// Fetching data with Promise...
392+
// Data received: { name: 'Jane Doe', age: 25 }
393+
// Name: Jane Doe
394+
// Age: 25
395+
// Data processed further: 50
396+
```
397+
398+
* **Explanation:** `fetchDataPromise` returns a Promise. The `.then()` method is used to handle the fulfilled state (when the data is successfully retrieved). The `.catch()` method handles the rejected state (if there's an error). Promise chaining allows you to perform a sequence of asynchronous operations in a more organized way.
399+
400+
**3. Async/Await**
401+
402+
* **What they are:** `async` and `await` make asynchronous code look and behave a bit more like synchronous code, making it even easier to read and understand. `async` is used to declare a function as asynchronous, and `await` is used inside an `async` function to pause execution until a Promise resolves (or rejects).
403+
404+
* **Why they're used:** Async/await simplifies asynchronous code even further than Promises, making it more concise and easier to follow the control flow. It's built on top of Promises.
405+
406+
* **Example:**
407+
408+
```javascript
409+
async function fetchDataAsync(url) {
410+
try {
411+
const data = await fetchDataPromise(url); // Wait for the Promise to resolve
412+
console.log("Data received (async/await):", data);
413+
console.log("Name:", data.name);
414+
console.log("Age:", data.age);
415+
return data;
416+
} catch (error) {
417+
console.error("Error (async/await):", error);
418+
}
419+
}
420+
421+
async function processDataAsync() {
422+
const data = await fetchDataAsync("some_url");
423+
console.log("Data processed further (async/await):", data.age * 2);
424+
}
425+
426+
427+
processDataAsync();
428+
console.log("Fetching data with async/await...");
429+
430+
// Output:
431+
// Fetching data with async/await...
432+
// Data received (async/await): { name: 'Jane Doe', age: 25 }
433+
// Name: Jane Doe
434+
// Age: 25
435+
// Data processed further (async/await): 50
436+
```
437+
438+
* **Explanation:** The `async` keyword makes `fetchDataAsync` and `processDataAsync` asynchronous functions. Inside `fetchDataAsync`, `await fetchDataPromise(url)` pauses execution until the Promise returned by `fetchDataPromise` resolves. The `try...catch` block handles any potential errors. `async/await` makes the code look much more like synchronous code, even though it's asynchronous under the hood.
439+
440+
**Key Differences Summarized:**
441+
442+
| Feature | Callbacks | Promises | Async/Await |
443+
|-----------------|-------------------------------------------|-------------------------------------------|------------------------------------------|
444+
| Syntax | Nested functions | `.then()`, `.catch()` | `async`, `await` |
445+
| Readability | Can become complex (callback hell) | Improved readability | Very readable, synchronous-like syntax |
446+
| Error Handling | Can be cumbersome | Easier with `.catch()` | Easier with `try...catch` |
447+
| Chaining | Difficult | Easy | Easy |
448+
| Under the Hood | Basic asynchronous mechanism | Built on callbacks, more structured | Built on Promises, syntactic sugar |
449+
450+
451+
In modern JavaScript development, Promises and especially async/await are the preferred way to handle asynchronous operations. They lead to cleaner, more maintainable, and easier-to-understand code. While callbacks are still used in some situations (especially in older code or with certain APIs), Promises and async/await are the recommended approach for most asynchronous tasks.
452+
453+
454+
## Closure
299455
A closure is a feature in JavaScript where an inner function has access to the outer (enclosing) function’s variables. In JavaScript, closures are created every time a function is created, at function creation time.
300456

301457
- Variables declared in the outer function’s scope.

0 commit comments

Comments
 (0)