|
4 | 4 |
|
5 | 5 | You can think of a Promise as an eventual value. It either succeeds with a particular success value, or it possibly fails with an error value.
|
6 | 6 |
|
7 |
| -<div class="flex text-3xl text-black bg-white"> |
| 7 | +<div class="my-4 flex text-center text-3xl text-black bg-white rounded shadow-lg"> |
8 | 8 | <div class="flex-grow p-4 bg-green-300 border border-green-400">
|
9 |
| - <div>Resolve with <div class="px-2 text-white bg-black border-4 border-white border-dashed">Value</div></div> |
| 9 | + <div class="space-y-2"> |
| 10 | + <div>Resolve with</div> |
| 11 | + <div class="px-4 text-white bg-black border-4 border-green-100 border-dashed rounded-full"> |
| 12 | + Value |
| 13 | + </div> |
| 14 | + </div> |
10 | 15 | </div>
|
11 |
| - <div class="flex-grow p-4 bg-orange-300 border-orange-400"> |
12 |
| - <div>Reject with <div class="px-2 text-white bg-black border-4 border-white border-dashed">Error</div></div> |
| 16 | + <div class="flex-grow p-4 bg-red-300 border border-red-400"> |
| 17 | + <div class="space-y-2"> |
| 18 | + <div>Reject with</div> |
| 19 | + <div class="px-4 text-white bg-black border-4 border-red-100 border-dashed rounded-full"> |
| 20 | + Error |
| 21 | + </div> |
| 22 | + </div> |
13 | 23 | </div>
|
14 | 24 | </div>
|
15 | 25 |
|
16 |
| -It either *resolves* to a success value, or it *rejects* with an error value. |
| 26 | +It either *resolves* to a success value: |
17 | 27 |
|
18 |
| -<div class="my-4 flex text-3xl text-black bg-white"> |
| 28 | +<div class="my-4 flex text-center text-3xl text-black shadow-lg"> |
19 | 29 | <div class="flex-grow p-4 bg-green-300 border border-green-400">
|
20 |
| - <div>✅ Resolved with <div class="px-2 text-white bg-green-700 border-4 border-green-900 rounded">Value</div></div> |
21 |
| - </div> |
22 |
| - <div class="flex-grow p-4 bg-orange-900 border-orange-900"> |
23 |
| - |
| 30 | + <div class="space-y-2"><div>✅ Resolved with</div> <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">42</div></div> |
24 | 31 | </div>
|
| 32 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
25 | 33 | </div>
|
26 | 34 |
|
27 |
| -<div class="my-4 flex text-3xl text-black bg-white"> |
28 |
| - <div class="flex-grow p-4 bg-green-900 border border-green-900"> |
29 |
| - |
30 |
| - </div> |
31 |
| - <div class="flex-grow p-4 bg-orange-300 border-orange-400"> |
32 |
| - <div>✅ Rejected with <div class="px-2 text-white bg-orange-700 border-4 border-orange-900 rounded">Error</div></div> |
| 35 | +```javascript |
| 36 | +// Succeed with the value 42 |
| 37 | +Promise.resolve(42); |
| 38 | + |
| 39 | +// Longer version of above |
| 40 | +new Promise((resolve, reject) => { |
| 41 | + resolve(42); |
| 42 | +}); |
| 43 | +``` |
| 44 | + |
| 45 | +Or it *rejects* with an error value: |
| 46 | + |
| 47 | +<div class="my-4 flex text-center text-3xl text-black"> |
| 48 | + <div class="flex-grow p-4 bg-green-300 border border-green-400 opacity-25"></div> |
| 49 | + <div class="flex-grow p-4 bg-red-300 border-red-400"> |
| 50 | + <div class="space-y-2"> |
| 51 | + <div>❌ Rejected with</div> |
| 52 | + <div class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</div> |
| 53 | + </div> |
33 | 54 | </div>
|
34 | 55 | </div>
|
35 | 56 |
|
| 57 | +```javascript |
| 58 | +// Fail with the error *out of stock* |
| 59 | +Promise.reject(new Error("out of stock")); |
| 60 | + |
| 61 | +// Longer version of above |
| 62 | +new Promise((resolve, reject) => { |
| 63 | + reject(new Error("out of stock")); |
| 64 | +}); |
| 65 | + |
| 66 | +// Alternate version of above |
| 67 | +new Promise((resolve, reject) => { |
| 68 | + throw new Error("out of stock"); |
| 69 | +}); |
| 70 | +``` |
| 71 | + |
36 | 72 | Once a Promise has receive its value, you can’t changed that value. If it was told it failed, it can’t be changed to succeed instead. And if it succeeded, it can’t later fail.
|
37 | 73 |
|
| 74 | +```javascript |
| 75 | +new Promise((resolve, reject) => { |
| 76 | + // Once a promise has been resolved or rejected |
| 77 | + resolve(42); |
| 78 | + // it can’t then be resolved again |
| 79 | + resolve(42); // Invalid! |
| 80 | + // or be rejected later |
| 81 | + reject(new Error("out of stock")); // Invalid! |
| 82 | +}); |
| 83 | +``` |
| 84 | + |
38 | 85 | ## Chaining Promises
|
39 | 86 |
|
40 | 87 | A Promise can create a _new_ Promise by calling `.then()` on it.
|
41 | 88 |
|
42 |
| -<div class="my-4 flex text-3xl text-black bg-white"> |
43 |
| - <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
44 |
| - <div>✅ Resolved with <div class="px-2 text-white bg-green-700 border-4 border-green-900 rounded">Value</div></div> |
| 89 | +<div class="my-4 flex flex-col text-center text-3xl text-black shadow-lg"> |
| 90 | + <div class="flex flex-row"> |
| 91 | + <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
| 92 | + <div class="space-y-2"> |
| 93 | + <div>✅ Resolved with</div> |
| 94 | + <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">42</div> |
| 95 | + </div> |
| 96 | + </div> |
| 97 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
| 98 | + </div> |
| 99 | + <div class="p-4 text-white bg-black"> |
| 100 | + <div>⬇ .then</div> |
| 101 | + <div>Multiply value by 2</div> |
| 102 | + </div> |
| 103 | + <div class="flex flex-row"> |
| 104 | + <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
| 105 | + <div class="space-y-2"> |
| 106 | + <div>✅ Resolved with</div> |
| 107 | + <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">84</div> |
| 108 | + </div> |
| 109 | + </div> |
| 110 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
| 111 | + </div> |
| 112 | +</div> |
| 113 | + |
| 114 | +```javascript |
| 115 | +Promise.resolve(42) |
| 116 | + .then(value => { |
| 117 | + return value * 2; |
| 118 | + }); |
| 119 | + |
| 120 | +// Longer version of above |
| 121 | +Promise.resolve(42) |
| 122 | + .then(value => { |
| 123 | + return Promise.resolve(value * 2); |
| 124 | + }); |
| 125 | +``` |
| 126 | + |
| 127 | +The callback to `.then()` can fail, either by throwing an error, or returning a rejected Promise: |
| 128 | + |
| 129 | +<div class="my-4 flex flex-col text-center text-3xl text-black shadow-lg"> |
| 130 | + <div class="flex flex-row"> |
| 131 | + <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
| 132 | + <div class="space-y-2"> |
| 133 | + <div>✅ Resolved with</div> |
| 134 | + <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">42</div> |
| 135 | + </div> |
| 136 | + </div> |
| 137 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
| 138 | + </div> |
| 139 | + <div class="p-4 text-white bg-black"> |
| 140 | + <div>⬇ .then</div> |
| 141 | + <div>Throw <span class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</span></div> |
45 | 142 | </div>
|
46 |
| - <div class="flex-grow p-4 bg-orange-900 border-orange-900"> |
47 |
| - |
| 143 | + <div class="flex flex-row"> |
| 144 | + <div class="flex-grow p-4 bg-green-300 border border-green-400 opacity-25"></div> |
| 145 | + <div class="flex-grow p-4 bg-red-300 border-red-400"> |
| 146 | + <div class="space-y-2"> |
| 147 | + <div>❌ Rejected with</div> |
| 148 | + <div class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</div> |
| 149 | + </div> |
| 150 | + </div> |
48 | 151 | </div>
|
49 | 152 | </div>
|
50 | 153 |
|
51 |
| -<div class="text-center">.then</div> |
| 154 | +```javascript |
| 155 | +Promise.resolve(42) |
| 156 | + .then(value => { |
| 157 | + throw new Error("out of stock"); |
| 158 | + }); |
| 159 | + |
| 160 | +// Longer version of above |
| 161 | +Promise.resolve(42) |
| 162 | + .then(value => { |
| 163 | + return Promise.reject(new Error("out of stock")); |
| 164 | + }); |
| 165 | + |
| 166 | +// Alternative version of above |
| 167 | +// Note the Promises can be created up-front. |
| 168 | +const outOfStockError = Promise.reject(new Error("out of stock")); |
| 169 | +Promise.resolve(42) |
| 170 | + .then(value => { |
| 171 | + return outOfStockError; |
| 172 | + }); |
| 173 | +``` |
52 | 174 |
|
53 |
| -<div class="my-4 flex text-3xl text-black bg-white"> |
54 |
| - <div class="flex-grow p-4 bg-green-900 border border-green-900"> |
55 |
| - |
| 175 | +If a Promise fails, any derived Promises will also fail. |
| 176 | + |
| 177 | +<div class="my-4 text-center text-3xl text-black shadow-lg"> |
| 178 | + <div class="flex flex-row"> |
| 179 | + <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
| 180 | + <div class="space-y-2"> |
| 181 | + <div>✅ Resolved with</div> |
| 182 | + <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">42</div> |
| 183 | + </div> |
| 184 | + </div> |
| 185 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
| 186 | + </div> |
| 187 | + <div class="p-4 text-white bg-black"> |
| 188 | + <div>⬇ .then</div> |
| 189 | + <div>Throw <span class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</span></div> |
| 190 | + </div> |
| 191 | + <div class="flex flex-row"> |
| 192 | + <div class="flex-grow p-4 bg-green-300 border border-green-400 opacity-25"></div> |
| 193 | + <div class="flex-grow p-4 bg-red-300 border-red-400"> |
| 194 | + <div class="space-y-2"> |
| 195 | + <div>❌ Rejected with</div> |
| 196 | + <div class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</div> |
| 197 | + </div> |
| 198 | + </div> |
56 | 199 | </div>
|
57 |
| - <div class="flex-grow p-4 bg-orange-300 border-orange-400"> |
58 |
| - <div>✅ Rejected with <div class="px-2 text-white bg-orange-700 border-4 border-orange-900 rounded">Error</div></div> |
| 200 | + <div class="text-white bg-black">⬇ .then</div> |
| 201 | + <div class="flex flex-row"> |
| 202 | + <div class="flex-grow p-4 bg-green-300 border border-green-400 opacity-25"></div> |
| 203 | + <div class="flex-grow p-4 bg-red-300 border-red-400"> |
| 204 | + <div class="space-y-2"> |
| 205 | + <div>❌ Rejected with</div> |
| 206 | + <div class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</div> |
| 207 | + </div> |
| 208 | + </div> |
59 | 209 | </div>
|
60 | 210 | </div>
|
61 | 211 |
|
| 212 | +```javascript |
| 213 | +Promise.resolve(42) |
| 214 | + .then(value => { |
| 215 | + throw new Error("out of stock"); |
| 216 | + }) |
| 217 | + .then(value => { |
| 218 | + // This will never get called as the previous promise was rejected |
| 219 | + }); |
| 220 | +``` |
| 221 | + |
| 222 | +A Promise chain can be recovered by calling `.catch()` and returning another value or Promise. |
| 223 | + |
| 224 | +<div class="my-4 text-center text-3xl text-black shadow-lg"> |
| 225 | + <div class="flex flex-row"> |
| 226 | + <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
| 227 | + <div class="space-y-2"> |
| 228 | + <div>✅ Resolved with</div> |
| 229 | + <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">42</div> |
| 230 | + </div> |
| 231 | + </div> |
| 232 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
| 233 | + </div> |
| 234 | + <div class="p-4 text-white bg-black"> |
| 235 | + <div>⬇ .then</div> |
| 236 | + <div>Throw <span class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</span></div> |
| 237 | + </div> |
| 238 | + <div class="flex flex-row"> |
| 239 | + <div class="flex-grow p-4 bg-green-300 border border-green-400 opacity-25"></div> |
| 240 | + <div class="flex-grow p-4 bg-red-300 border-red-400"> |
| 241 | + <div class="space-y-2"> |
| 242 | + <div>❌ Rejected with</div> |
| 243 | + <div class="px-4 text-white bg-red-700 border-4 border-red-900 rounded-full">Error: out of stock</div> |
| 244 | + </div> |
| 245 | + </div> |
| 246 | + </div> |
| 247 | + <div class="p-4 text-white bg-black"> |
| 248 | + <div>⬇ .catch</div> |
| 249 | + <div>Return <span class="px-4 text-white bg-gray-700 border-4 border-gray-900 rounded-full">3</span></div> |
| 250 | + </div> |
| 251 | + <div class="flex flex-row"> |
| 252 | + <div class="flex-grow p-4 bg-green-300 border border-green-400"> |
| 253 | + <div class="space-y-2"> |
| 254 | + <div>✅ Resolved with</div> |
| 255 | + <div class="px-4 text-white bg-green-700 border-4 border-green-900 rounded-full">3</div> |
| 256 | + </div> |
| 257 | + </div> |
| 258 | + <div class="flex-grow p-4 bg-red-300 border-red-400 opacity-25"></div> |
| 259 | + </div> |
| 260 | +</div> |
| 261 | + |
| 262 | +```javascript |
| 263 | +export const a = Promise.resolve(42) |
| 264 | + .then(value => { |
| 265 | + throw new Error("out of stock"); |
| 266 | + }) |
| 267 | + .catch(error => { |
| 268 | + return 3; |
| 269 | + }); |
| 270 | + |
| 271 | +// Same as above |
| 272 | +export const b = Promise.resolve(42) |
| 273 | + .then(value => { |
| 274 | + throw new Error("out of stock"); |
| 275 | + }) |
| 276 | + .catch(error => { |
| 277 | + return Promise.resolve(3); |
| 278 | + }); |
| 279 | + |
| 280 | +// Same as above |
| 281 | +const fallbackPromise = Promise.resolve(3); |
| 282 | +export const c = Promise.resolve(42) |
| 283 | + .then(value => { |
| 284 | + throw new Error("out of stock"); |
| 285 | + }) |
| 286 | + .catch(error => { |
| 287 | + return fallbackPromise; |
| 288 | + }); |
| 289 | + |
| 290 | +// Same as above |
| 291 | +const promiseThatWillFail = Promise.resolve(42).then(value => { |
| 292 | + throw new Error("out of stock"); |
| 293 | +}); |
| 294 | +export const d = promiseThatWillFail.catch(error => { |
| 295 | + return fallbackPromise; |
| 296 | +}); |
| 297 | +``` |
| 298 | + |
| 299 | +---- |
| 300 | + |
62 | 301 | ## Promises are eager
|
63 | 302 |
|
64 | 303 | Let's compare two code samples. How many times will we see _Creating value_ logged?
|
|
0 commit comments