You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Listing 1. Asynchronous XMLHttpRequest using a promise
27
+
Listing 1. Asynchronous `XMLHttpRequest` (and `fetch` alternative) using a promise
27
28
28
-
The `getJSON()` function call in Listing 1 returns a `promise` that resolves to some value converted from JSON data received from some remote API end point. The `fetchJSON()` function does the same, using a more modern browser Web API.
29
+
The `getJSON()` function in Listing 1 returns a `promise` that resolves to some value converted from JSON data received from some remote API end point. The `fetchJSON()` function does the same, using a more modern browser Web API.
29
30
30
31
## What is a promise?
31
32
@@ -35,30 +36,34 @@ Why is a JavaScript ES6 `promise` called a 'promise'? Here is a snippet from the
35
36
noun<br>
36
37
1 a declaration or assurance that one will do something or that a particular thing will happen
37
38
38
-
This pretty well sums up what a promise means in JavaScript: something that will be delivered in the future (if and when the promise is *fulfilled*). Traditionally, *callbacks* are used as a way to receive the data that is delivered asynchronously (meaning that the data is not likely to be available at the time it is requested but can be expected 'to happen' some time later). Using callbacks can quickly become unwieldy when dealing with many asynchronous events (e.g., ajax calls), especially when they depend on each other (google for *callback hell*).
39
+
This pretty well sums up what a promise means in JavaScript: something that will be delivered in the future (if and when the promise is *fulfilled*).
40
+
41
+
Traditionally, *callbacks* are used as a way to receive the data that is delivered asynchronously (meaning that the data is not likely to be available at the time it is requested but can be expected 'to happen' some time later). Using callbacks can quickly become unwieldy when dealing with many asynchronous events (e.g., ajax calls), especially when they depend on each other (google for *callback hell*).
39
42
40
43
JavaScript ES6 introduces promises as a better alternative for callbacks when dealing with asynchronous events.
41
44
42
45
We can state a number of simple facts about ES6 promises:
43
46
44
-
- A promise is a JavaScript object (`typeof somePromise === 'object'`).
45
-
- Because a promise is an ordinary JavaScript object you can pass it around as an argument to a function, return it from a function, assign it to a variable, etc.
46
-
- You can create one yourself by calling the ES6 `Promise` constructor function with `new` (like we're doing in Listing 1 above), then call `resolve` when results are ready or `reject` on detecting an error.
47
+
- A promise is a JavaScript object (`typeof somePromise === 'object'`) that serves as a placeholder for a (future) value.
48
+
- Because a promise is an ordinary JavaScript object you can pass it around as an argument to a function, return it from a function, assign it to a variable, push it to an array, etc.
49
+
- You can create one yourself by calling the ES6 `Promise` constructor function with `new` (as we're doing in Listing 1 above), then call `resolve` when results are ready or `reject` on detecting an error.
47
50
- Sometimes you can get a ready-made promise by calling an appropriate API or library function, like the `fetch` Web API function in Listing 1.
48
-
- Internally, a promise can be in three states:
51
+
- Internally, a promise can be in one of three states:
49
52
-**pending**: the asynchronous result is still awaiting delivery
50
53
-**fulfilled**: the asynchronous result has been delivered and ready (`resolve` was called)
51
54
-**rejected**: an error was encountered: the promise could not be fulfilled (`reject` was called)
55
+
- A promise that is no longer pending because it was either fulfilled to rejected is said to be _settled_.
56
+
- A promise that is _settled_ has reached its final state. Its state and value can no longer be changed.
52
57
53
58
## The .then() method
54
59
55
-
A promise object exposes a `.then()` method through which you can obtain its fulfilled result or an error value in the case the promise was rejected:
60
+
A promise exposes a `.then()` method through which you can obtain its fulfilled value or an error value in the case the promise was rejected:
56
61
57
62
```js
58
63
somePromise.then(onFulfilled, onRejected)
59
64
```
60
65
61
-
The `.then()` method takes two **optional**functions (technically they could be called *callbacks*), the first one dealing with the 'happy' scenario (the promise is fulfilled) and the second one dealing with the error case (the promise is rejected). If you are only interested in the success case you can leave out the second callback:
66
+
The `.then()` method takes two **optional** callbacks, the first one dealing with the 'happy' scenario (the promise is fulfilled) and the second one dealing with the error case (the promise is rejected). If you are only interested in the success case you can leave out the second callback:
62
67
63
68
```js
64
69
somePromise.then(onFulfilled)
@@ -70,35 +75,32 @@ If you are only interested in the error case, you can pass `null` for the first
70
75
somePromise.then(null, onRejected)
71
76
```
72
77
73
-
or you can use a second method exposed by a promise object, which is just a short-hand for calling `then()` with `null` as its first argument:
78
+
or you can use a second method exposed by a promise, which is just a short-hand for calling `then()` with `null` as its first argument:
74
79
75
80
```js
76
81
somePromise.catch(onRejected)
77
82
```
78
83
79
-
It is important to understand that the `.then()` method returns a new promise that resolves to the return value of the `onFulfilled` callback (if specified) in case of the 'happy' scenario or the return value of the `onRejected` callback (if specified) in case of an error. If the return value of these functions is a plain JavaScript value, the new promise is immediately fulfilled with that value. If the return value is yet another promise then that promise itself is the fulfillment value. If the function does not return a value, the new promise is immediately fulfilled with the value `undefined`.
84
+
> Note: the callback functions passed as arguments to the `.then()` method are always called asynchronously, even if the promise was already settled.
85
+
86
+
It is also important to understand that the `.then()` method returns a new promise that resolves to the return value of the `onFulfilled` callback (if specified) in case of the 'happy' scenario or the return value of the `onRejected` callback (if specified) in case of an error. If the return value of these functions is a plain JavaScript value, the new promise is immediately fulfilled with that value. If the return value is yet another promise then that promise itself is the fulfillment value. If the function does not return a value, the new promise is immediately fulfilled with the value `undefined`.
80
87
81
88
Because `.then()` (and `.catch`) return new promises, you can chain them together such that your code can be read as: do *this*, then do *that* and then *that*, etc.:
Let's analyze the code snippet of Listing 2 a bit more in light of what we have discussed up until now.
95
-
96
-
1. The `getJSON(HYFReposApiEndpoint)` function call returns a promise that will be fulfilled with an array of objects, describing the GitHub repositories of the HackYourFuture organisation.
97
-
2. In the first `.then()` the arrow function `res => getHtmlRepoList(res)` takes the place of `onFulfilled` from the discussion above. The *array-of-objects* from step 1 is passed as the `res` parameter and subsequently passed on to the `getHtmlReposList(res)` function call. This function in its turn returns a string of HTML tags, which becomes the fulfillment value of the new promise returned by the first `.then()`.
98
-
3. In the second `.then()` the arrow function `html => renderList($repoList, html)` uses the HTML string (the fulfillment value of the first `.then()`) to render the repo data to DOM.
99
-
4. The callback function from `.catch()` is only called when one of the promises in the chain is rejected. Otherwise is not called at all.
0 commit comments