Skip to content

Commit b58a486

Browse files
committed
getting started with Promise
1 parent a293a68 commit b58a486

File tree

2 files changed

+119
-9
lines changed

2 files changed

+119
-9
lines changed

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

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
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) |
99
| [Multiple Callbacks and setTimeout(0)](#multiple-callbacks-and-settimeout0) |
10+
| [Getting Started with Promises](#getting-started-with-promises) |
1011

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

@@ -264,3 +265,101 @@ This example serves to demonstrate the possibility of nesting asynchronous opera
264265
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.
265266

266267
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.
268+
269+
## Getting Started with Promises
270+
271+
We've covered a lot about working with asynchronous code, which is crucial knowledge for anyone diving into JavaScript web development. It's like a key tool you can't do without.
272+
273+
Now, let's shift our attention to something important: making our code easier to understand. In our previous code snippet, you may find the complexity and confusion in terms of reading.
274+
275+
When we end up with situations where callbacks are nested inside one another (like in our example), it's called "callback hell." This term captures the difficulty of reading and organizing such code. It's hard to keep track of what's happening inside what, and figuring out which parts can talk to each other becomes a puzzle.
276+
277+
This kind of complex code isn't fun to work with. But guess what? JavaScript comes to the rescue with a solution called "promises." It's like a cleaner and more organized way to handle these situations.
278+
279+
<img src="https://drive.google.com/uc?export=view&id=1Imx6Zn-yw0z82WJTY89vn_uKoqiAHvMA" width="600" height="390" alt="academind slide">
280+
281+
***A [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) in JavaScript is an object that represents the eventual completion or failure of an asynchronous operation. It's a way to handle asynchronous code in a more organized and readable manner. Promises provide a structured approach to managing callbacks, making it easier to work with complex asynchronous operations.***
282+
283+
Here's how promises work:
284+
285+
1. **State**: A promise can be in one of three states:
286+
287+
- **Pending**: The asynchronous operation is ongoing and the promise is waiting for its completion.
288+
- **Fulfilled**: The operation has completed successfully, and the promise has a result value.
289+
- **Rejected**: The operation encountered an error or failure, and the promise has a reason for the failure.
290+
291+
2. **Chaining**: Promises can be chained together, allowing you to perform a sequence of asynchronous operations in a more linear and readable way. This is particularly useful when you have multiple asynchronous tasks that depend on each other (a basic example is shown in image above).
292+
293+
3. **Error Handling**: Promises have built-in mechanisms for error handling. You can attach `.catch()` to handle errors that occur during the promise chain.
294+
295+
Coming back to our example used previously, let's update it to show the usage of `Promise`.
296+
297+
```javascript
298+
const button = document.querySelector('button');
299+
300+
// Wrapping setTimeout() inside `setTimer()` function and it returns Promise object.
301+
// This Promise object will now handle the success or failure outcomes.
302+
// So, point here is, since these web API methods (setTimeout() and navigator.geolocation.getCurrentPosition())
303+
// does not support Promise object but only callbacks, hence, for demonstration,
304+
// they are wrap under Promise object.
305+
306+
const setTimer = (duration) => {
307+
const promise = new Promise((resolve, reject) => {
308+
setTimeout(() => {
309+
resolve('Done!');
310+
}, duration);
311+
});
312+
return promise;
313+
};
314+
315+
function trackUserHandler() {
316+
navigator.geolocation.getCurrentPosition(
317+
posData => {
318+
setTimer(2000).then(data => {
319+
console.log(data, posData);
320+
});
321+
}, error => {
322+
console.log(error);
323+
});
324+
setTimer(1000).then(() => {
325+
console.log('Timer Done!');
326+
});
327+
console.log("Getting position...");
328+
}
329+
330+
button.addEventListener('click', trackUserHandler);
331+
```
332+
333+
Let's break down what's happening here. Unfortunately, `setTimeout()` and `getCurrentPosition()` functions don't directly work with promises, which are a modern way of handling asynchronous operations. Promises make it easier to manage and write code that involves waiting for something to finish, like a timer or getting a user's location.
334+
335+
So, let's say we want to use promises with `setTimeout()` to make it more manageable. Here's how we do it step by step:
336+
337+
1. We create a new function called `setTimer()` that takes a duration argument.
338+
339+
2. Inside `setTimer()`, we create a new Promise. A promise is like a special container that holds the result of an asynchronous operation.
340+
341+
3. We use `setTimeout()` inside the promise. When the timer is done (after the given duration), we resolve the promise with a message like "Done!".
342+
343+
4. We return the promise. This way, when we use `setTimer()`, we can wait for the timer to finish and get the result using the promise's `then` method.
344+
345+
5. We have a function called `trackUserHandler()` that's triggered when a button is clicked.
346+
347+
6. Inside `trackUserHandler()`, we use `getCurrentPosition()` to get the user's location. However, we wrap this whole process inside a `setTimer(2000)` promise. This means we'll wait for both the timer and the location fetching to finish.
348+
349+
7. If the location is fetched successfully, we log the location data along with the "Done!" message.
350+
351+
8. Then, we use `setTimer(1000)` to wait for another timer before logging "Timer Done!".
352+
353+
9. Finally, we log "Getting position..." immediately.
354+
355+
In essence, we're making sure our code doesn't wait around for timers or location fetching. *Instead, we're using promises to manage these operations, making our code more efficient and easier to read.*
356+
357+
The concept of promises might seem a bit tricky at first, but it's a powerful tool that helps us write better asynchronous code. It's like telling JavaScript, "Hey, wait for this to finish, and then do something with the result."
358+
359+
Readings:
360+
361+
- [JavaScript Promises In 10 Minutes](https://www.youtube.com/watch?v=DHvZLI7Db8E)
362+
363+
- [JavaScript Promise Tutorial – How to Resolve or Reject Promises in JS](https://www.freecodecamp.org/news/javascript-promise-tutorial-how-to-resolve-or-reject-promises-in-js/)
364+
365+
- [JavaScript Promise and Promise Chaining](https://www.programiz.com/javascript/promise)

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

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

4+
// Wrapping setTimeout() inside `setTimer()` function and it returns Promise object.
5+
// This Promise object will now handle the success or failure outcomes.
6+
// So, point here is, since these web API methods (setTimeout() and navigator.geolocation.getCurrentPosition())
7+
// does not support Promise object but only callbacks, hence, for demonstration, they are encapsulated under
8+
// Promise object.
9+
const setTimer = (duration) => {
10+
const promise = new Promise((resolve, reject) => {
11+
setTimeout(() => {
12+
resolve('Done!');
13+
}, duration);
14+
});
15+
return promise;
16+
};
17+
418
function trackUserHandler() {
519
navigator.geolocation.getCurrentPosition(
620
posData => {
7-
setTimeout(
8-
() => {
9-
console.log(posData);
10-
}, 2000
11-
);
21+
setTimer(2000).then(data => {
22+
console.log(data, posData);
23+
});
1224
}, error => {
1325
console.log(error);
1426
});
15-
setTimeout(
16-
() => {
17-
console.log("Timer done");
18-
}, 0);
27+
setTimer(1000).then(() => {
28+
console.log('Timer Done!');
29+
});
1930
console.log("Getting position...");
2031
}
2132

0 commit comments

Comments
 (0)