Skip to content

Commit a293a68

Browse files
committed
learn about multiple callbacks
1 parent 5561baf commit a293a68

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

Async-JS-Promises-and-Callbacks/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
| [Understanding Asynchronous Code Execution ("Async Code")](#understanding-asynchronous-code-execution-async-code) |
77
| [Blocking Code and The "Event Loop"](#blocking-code-and-the-event-loop) |
88
| [Sync + Async Code - The Execution Order](#sync--async-code---the-execution-order) |
9+
| [Multiple Callbacks and setTimeout(0)](#multiple-callbacks-and-settimeout0) |
910

1011
## Understanding Synchronous Code Execution ("Sync Code")
1112

@@ -225,3 +226,41 @@ As before, if we have code following the `getCurrentPosition` call, such as logg
225226
Thus, even if `getCurrentPosition` executes instantly, any code following it will always run before the success or error callback functions. This behavior illustrates how asynchronous operations work, ensuring that code within the callback functions cannot execute before the code outside the callback, as the browser follows the event loop and message queue pattern.
226227

227228
Upon reloading the page, clicking "Track Me," and then blocking access, we observe that the "Getting position..." log is displayed instantly, showcasing the non-blocking nature of JavaScript.
229+
230+
## Multiple Callbacks and setTimeout(0)
231+
232+
For the purpose of learning, let's introduce a 2-second timer before displaying the response. To achieve this, an additional anonymous function is required within the existing callback. Inside this nested function, the `posData` can be accessed and logged. This is made possible due to the concept of closure, where the function is nested within another, allowing access to variables within the outer function.
233+
234+
```javascript
235+
const button = document.querySelector('button');
236+
237+
function trackUserHandler() {
238+
navigator.geolocation.getCurrentPosition(
239+
posData => {
240+
setTimeout(
241+
() => {
242+
console.log(posData);
243+
}, 2000
244+
);
245+
}, error => {
246+
console.log(error);
247+
});
248+
setTimeout(
249+
() => {
250+
console.log("Timer done");
251+
}, 0);
252+
console.log("Getting position...");
253+
}
254+
255+
button.addEventListener('click', trackUserHandler);
256+
```
257+
258+
However, the logging of `posData` is delayed by 2 seconds due to the timer, introduced for illustrative purposes. This situation results in a callback within another callback, both of which are part of the broader `trackUserHandler` callback. As this nesting of callbacks becomes more complex, the code's readability and maintenance can become challenging over time.
259+
260+
To check the functionality, I save the changes, reload the page, click "Track Me," grant access, and observe the sequence. The location retrieval takes a moment, and after an additional 2 seconds, the position data is displayed.
261+
262+
This example serves to demonstrate the possibility of nesting asynchronous operations. The timer is initiated only after the location retrieval is completed, that is, once the outer callback function executes. Notably, when dealing with timers, it's essential to understand that setting a timer of zero doesn't guarantee immediate execution. The browser's execution route via the message queue and the event loop introduces a minimal time delay.
263+
264+
As an experiment, if I set a timer of zero immediately before the `console.log("Getting position...")` line, the result is intriguing. Reloading the page and clicking "Track Me," I observe that "Getting position..." logs first, followed by "Timer done," even though the timer is set to zero. This behavior occurs because the execution flow requires the browser to pass through the message queue and the event loop, ultimately leading to the sequence I described.
265+
266+
In essence, the minimum time for executing a callback is defined by the timer value, but it's not a guaranteed time. The browser and JavaScript attempt to execute the function at the specified minimum time, but it's subject to the state of the call stack. If the call stack is occupied, that task will be prioritized. As a result, the sequence is influenced by the passage through the message queue and event loop, with the call stack's status playing a pivotal role.

Async-JS-Promises-and-Callbacks/summary-with-code/app.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@ const button = document.querySelector('button');
22
const output = document.querySelector('p');
33

44
function trackUserHandler() {
5-
navigator.geolocation.getCurrentPosition(posData => {
6-
console.log(posData);
5+
navigator.geolocation.getCurrentPosition(
6+
posData => {
7+
setTimeout(
8+
() => {
9+
console.log(posData);
10+
}, 2000
11+
);
712
}, error => {
813
console.log(error);
914
});
15+
setTimeout(
16+
() => {
17+
console.log("Timer done");
18+
}, 0);
1019
console.log("Getting position...");
1120
}
1221

0 commit comments

Comments
 (0)