Skip to content

Commit 4ac5a50

Browse files
committed
convert-callback-to-promise-async-await
1 parent 8e687a8 commit 4ac5a50

23 files changed

+111
-31
lines changed

Javascript/async-await-master-notes/README.md renamed to Promise-Async-Await-Sequential-Execution/async-await-master-notes/README.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ async function asyncF() {
1212
return 'TEST';
1313
}
1414
```
15+
16+
**Any async function returns a promise implicitly, and the resolve value of the promise will be whatever you return from the function**
17+
1518
## Async - declares an asynchronous function (async function someName(){...}).
1619

1720
- Automatically transforms a regular function into a Promise.
@@ -22,12 +25,12 @@ async function asyncF() {
2225

2326
- When placed in front of a Promise call, await forces the rest of the code to wait until that Promise finishes and returns a result.
2427
- This will pause the async function and wait for the Promise to resolve prior to moving on.
25-
- Await works only with Promises, it does not work with callbacks.
28+
- **Await works only with Promises, it does not work with callbacks.**
2629
- Await can only be used inside async functions.
2730

2831
## Thumb Rules
2932

30-
- await blocks the code execution within the async function, of which it(await statement) is a part.
33+
- await blocks the code execution within the async function, of which it (i.e. the 'await' statement) is a part.
3134

3235
- There can be multiple await statements within a single async function.
3336

@@ -61,8 +64,6 @@ async function f(){
6164

6265
In most previous examples, we assumed that the promises resolve successfully. Hence, await-ing on a promise returned a value. If a promise we await for fails, this will result in an exception within the async function. We can use standard try/catch to handle it, we just need to wrap our await calls like this:
6366

64-
65-
6667
```
6768
async function doSomethingAsync(){
6869
try {
@@ -76,6 +77,7 @@ async function doSomethingAsync(){
7677
```
7778

7879
**Async function without a try/catch block.**
80+
7981
```
8082
async function doSomethingAsync(){
8183
// This async call may fail.
@@ -89,4 +91,4 @@ doSomethingAsync().
8991
.catch(errorHandler);
9092
```
9193

92-
It's important to choose which method of error handling you prefer and stick to it. Using both try/catch and .catch() at the same time will most probably lead to problems.
94+
It's important to choose which method of error handling you prefer and stick to it. Using both try/catch and .catch() at the same time will most probably lead to problems.
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
1-
require('es6-promise').polyfill();
2-
require('isomorphic-fetch');
1+
require("es6-promise").polyfill();
2+
require("isomorphic-fetch");
33

4-
/* I had to use the above packages as withiout it the simple fetch.('url') wont work
4+
/* I had to use the above packages as without it the simple fetch.('url') wont work
55
https://stackoverflow.com/questions/36484156/es6-fetch-is-undefined
66
https://www.npmjs.com/package/isomorphic-fetch */
77

88
// APPROACH-1 PROMISE WAY >> First deal with an network request with Promise approach
99

1010
getJSON = () => {
11-
12-
return new Promise((resolve) => {
13-
fetch('https://tutorialzine.com/misc/files/example.json')
14-
15-
// The data from the request is available in a .then block
16-
// We return the result using resolve.
11+
return new Promise(resolve => {
12+
fetch("https://tutorialzine.com/misc/files/example.json")
13+
// The data from the request is available in a .then block
14+
// We return the result using resolve.
1715
.then(json => {
1816
resolve(json);
19-
console.log('Successively fetched');
20-
})
21-
})
22-
}
17+
console.log("Successively fetched");
18+
});
19+
});
20+
};
2321

24-
getJSON() // Will fetch and then print "Successively fetched"
22+
getJSON(); // Will fetch and then print "Successively fetched"
2523

2624
/* EXPLANATION OF THE ABOVE - The Fetch API provides an interface for making network requests, returning Promises for us to resolve. To use it to get the data, I chain together a single .then callback. The callback receives the Response object and return back its JSON data. And then console.logs it.
27-
*/
25+
*/
2826

2927
/* REMEMBER THE FETCH SYNTAX
3028
@@ -38,21 +36,18 @@ fetch(url) // Call the fetch function passing the url of the API as a parameter
3836
3937
*/
4038

41-
4239
// APPROACH-2 With async-await
4340

44-
// The async keyword will automatically create a new Promise and return it.
41+
// The async keyword will automatically create a new Promise and return it. Any async function returns a promise implicitly, and the resolve value of the promise will be whatever you return from the function
4542

4643
const getJSONAsync = async () => {
47-
4844
// The await keyword saves us from having to write a .then() block.
49-
let json = await fetch('https://tutorialzine.com/misc/files/example.json')
50-
51-
return json && console.log('Fetched with async');
45+
let json = await fetch("https://tutorialzine.com/misc/files/example.json");
5246

53-
}
47+
return json && console.log("Fetched with async");
48+
};
5449

55-
getJSONAsync() // Will fetch and then print "Fetched with async"
50+
getJSONAsync(); // Will fetch and then print "Fetched with async"
5651

5752
/* The await expression causes async function execution to pause until a Promise is resolved, that is fulfilled or rejected, and to resume execution of the async function after fulfillment. When resumed, the value of the await expression is that of the fulfilled Promise.
5853
@@ -71,4 +66,4 @@ const foo = async () => {
7166
7267
Other than the syntax used, both functions are completely identical - they both return Promises and resolve with the JSON response from fetch().
7368
74-
*/
69+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
First note, - **Await works only with Promises, it does not work with callbacks. So to implement async-await to a function/code, I first have to convert the callback to a Promise **
2+
3+
Fist let's take the simplest of example. `setTimeout` is a straightforward browser API that waits for a specified period of time and then executes a callback. A standard use looks like this:
4+
5+
```js
6+
function doStuff() {
7+
/_..._/;
8+
}
9+
10+
setTimeout(doStuff, 300);
11+
```
12+
13+
A Promise-based API for this function would likely look something like this code.
14+
15+
`timeout(300).then(doStuff)`
16+
17+
We can create an API like that using setTimeout. To do that, we’ll need a function timeout which takes a timeout variable and returns a Promise.
18+
19+
You can define A+ compliant Promises using the Promise constructor, which expects a single function as an argument. That function takes 2 arguments, a resolve function and a reject function. The wonderful thing is that under the covers these are just callback functions that the Promise api glosses over.
20+
21+
```js
22+
function timeout(delay) {
23+
return new Promise(function(resolve, reject) {
24+
setTimeout(resolve, delay);
25+
});
26+
}
27+
```
28+
29+
We don’t use the reject callback, since setTimeout doesn’t provide any hooks for an error state. So we pass resolve as the callback to setTimeout, and that is all we need. Now we have a great chainable setTimeout function that we could include in a Promise chain.
30+
31+
##### Now lets do a slightly more complicated version of the same exercise
32+
33+
[Source Code](https://github.com/coreyc/converting-callbacks/blob/master/index.js)
34+
35+
#### Callback version
36+
37+
```js
38+
const callbackFn = (firstName, callback) => {
39+
setTimeout(() => {
40+
if (!firstName) return callback(new Error("no first name passed in!"));
41+
42+
const fullName = `${firstName} Doe`;
43+
44+
return callback(fullName);
45+
}, 2000);
46+
};
47+
48+
callbackFn("John", console.log);
49+
callbackFn(null, console.log);
50+
```
51+
52+
We're using the setTimeout() function in order to make our function asynchronous. In addition to setTimeout(), other asynchronous operations you're likely to see in the real-world are: AJAX and HTTP calls, database calls, filesystem calls (in the case of Node, if no synchronous version exists), etc.
53+
54+
In this function, we "reject" it if the first name argument is null. When we do pass in the firstName argument, the callback function (almost always the last argument in a callback-based function's argument list) gets called and returns our value after the 2 seconds set in setTimeout().
55+
56+
#### Promise version - And here's the Promise-based version of that function:
57+
58+
```js
59+
const promiseFn = firstName => {
60+
return new Promise((resolve, reject) => {
61+
setTimeout(() => {
62+
if (!firstName) reject(new Error("no first name passed in!"));
63+
64+
const fullName = `${firstName} Doe`;
65+
66+
resolve(fullName);
67+
}, 2000);
68+
});
69+
};
70+
71+
promiseFn("Jane").then(console.log);
72+
promiseFn().catch(console.log);
73+
```
74+
75+
Converting to a Promise-based function is actually pretty simple. Look at the below diagram for a visual explanation:
76+
77+
<img src="convert-callback-to-promise-async-await-1.png">
78+
79+
#### Further reading
80+
81+
1> https://benmccormick.org/2015/12/30/es6-patterns-converting-callbacks-to-promises
82+
83+
2> https://dev.to/ccleary00/how-to-rewrite-a-callback-function-in-promise-form-and-asyncawait-form-in-javascript-410e

Javascript/sequential-execution-of-codes-React-Node-Context-Master-Notes/multiple-sequential-axio-request.md renamed to Promise-Async-Await-Sequential-Execution/sequential-execution-of-codes-React-Node-Context-Master-Notes/multiple-sequential-axio-request.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ I can use async and await
1414
}
1515
```
1616

17-
A very importnat use case of this is, when restting password. Before resetting the password, I have to make sure, that the unique-link sent to the user is valid (Not expired and the same that was sent to him) - So, for this, in the same password-reset function, I have to first make an axios call to an API endpoint, which will validate that the link sent to the user is valid. And only if this API call returns a valid respoonse, I will fire the second API call to the endpoint to actually reset the password.
17+
A very important use case of this is, when resetting password. Before resetting the password, I have to make sure, that the unique-link sent to the user is valid (Not expired and the same that was sent to him) - So, for this, in the same password-reset function, I have to first make an axios call to an API endpoint, which will validate that the link sent to the user is valid. And only if this API call returns a valid respoonse, I will fire the second API call to the endpoint to actually reset the password.
1818

1919
Extract from a PasswordReset Component production grade project below
2020

@@ -96,4 +96,4 @@ Extract from a PasswordReset Component production grade project below
9696

9797
#### Further Reading
9898

99-
https://stackoverflow.com/questions/47343225/making-2-sequential-requests-with-axios-second-request-depends-on-the-response
99+
https://stackoverflow.com/questions/47343225/making-2-sequential-requests-with-axios-second-request-depends-on-the-response

0 commit comments

Comments
 (0)