|
1 | 1 | # Promise |
2 | 2 |
|
3 | | - |
4 | | -```compare plus="Plus" minus="Minus" |
5 | | -+ One |
6 | | -- two |
7 | | -``` |
8 | | - |
9 | 3 | A promise is an object of the built-in `Promise` class. |
10 | 4 |
|
11 | 5 | The promise object has two main internal properties: `state` and the `result`. |
@@ -224,98 +218,59 @@ promise.then( |
224 | 218 | promise.then(script => alert('One more handler to do something else!')); |
225 | 219 | ``` |
226 | 220 |
|
227 | | -We can immediately see few benefits over the callback-based syntax in the example above. |
228 | | -
|
229 | | -| Callbacks | Promises | |
230 | | -|-----------|----------| |
231 | | -| We must have `callback` function when calling `loadScript`. So we must know what to do with the result *before* we make a call for it. | Promises allow us to code more naturally. First we run `loadScript`, then code what we do with the result. | |
232 | | -|There can be only one callback. | We can call `.then` as many times as we want. | |
| 221 | +We can immediately see few benefits over the callback-based syntax: |
233 | 222 |
|
| 223 | +```compare minus="Callbacks" plus="Promises" |
| 224 | +- We must have `callback` function available when calling `loadScript`. So we must know what to do with the result *before* we make a call for it. |
| 225 | +- There can be only one callback. |
| 226 | ++ Promises allow us to code more naturally. First we run `loadScript`, and `.then` code what we do with the result. |
| 227 | ++ We can call `.then` as many times as we want. |
| 228 | +``` |
234 | 229 |
|
235 | | -We can call `promise.then` at any time. Maybe much later, when we really need that script. |
236 | | -
|
237 | | -1. We can call `promise.then` as many times as want, so we can add any number of handlers. |
238 | | -3. The `promise` object can be passed around, new handlers can be added where needed in other parts of the code. |
239 | | -
|
240 | | -So promises give us flexibility. But there's more. We can chain promises and use `async` functions and so on. We'll see that in the next chapters. |
241 | | -
|
242 | | -Read the notes below for better understanding of promise objects. |
243 | 230 |
|
244 | | -````warn header="Once a promise settles, it can't be changed" |
245 | | -When either `resolve` or `reject` is called -- the state change is final. The argument of `resolve/reject` is saved in the promise object. |
| 231 | +So promises give us better code flow and flexibility. But there's more. We'll see that in the next chapters. |
246 | 232 |
|
247 | | -Future calls of `resolve/reject` are ignored, so there's no way to "re-resolve" or "re-reject" a promise. |
| 233 | +````smart header="On settled promises `then` runs immediately" |
| 234 | +We can add `.then/catch` at any time. |
248 | 235 |
|
249 | | -For instance, here only the first `resolve` works: |
| 236 | +If the promise has not settled yet, then it will wait for the result. Otherwise, if the promise has already settled, then `promise.then/catch` handlers run immediately: |
250 | 237 |
|
251 | 238 | ```js run |
252 | | -let promise = new Promise(function(resolve, reject) { |
253 | | - resolve("done!"); // immediately fulfill with the result: "done" |
254 | | -
|
255 | | - // a subsequent resolve is ignored |
256 | | - setTimeout(() => resolve("..."), 1000); |
257 | | - // a subsequent reject is ignored |
258 | | - setTimeout(() => reject(new Error("..."), 2000)); |
259 | | -}); |
260 | | -
|
261 | | -promise.then(result => alert(result), () => alert("Never runs")); |
262 | | -``` |
263 | | -```` |
264 | | - |
| 239 | +let promise = new Promise(resolve => resolve("done!")); // immediately resolve |
265 | 240 |
|
266 | | -````smart header="A promise may resolve immediately, doesn't have to be asynchronous" |
267 | | -As we've seen from the example above, a promise may call resolve/reject without delay: |
268 | | -
|
269 | | -```js run |
270 | | -new Promise(function(resolve, reject) { |
271 | | - resolve("done!"); // immediately fulfill with the result: "done" |
272 | | -}).then(alert); |
| 241 | +promise.then(alert); // done! (without delay) |
273 | 242 | ``` |
274 | 243 |
|
275 | | -That's normal, sometimes it turns out that there's no asynchronous job to be done. For instance, if we have a cached result. |
276 | | -```` |
277 | | - |
278 | | -````smart header="On settled promises `then` runs immediately" |
279 | | -We can add `.then/catch` at any time. |
280 | 244 |
|
281 | | -If the promise has not settled yet, then it will wait for the result. |
| 245 | +To be precise -- handlers are always asynchronous, but if the promise is settled they run as soon as possible, similar to `setTimeout(...,0)`. |
282 | 246 |
|
283 | | -Otherwise, if the promise has already resolved/rejected, then subsequent `promise.then/catch` handlers are executed immediately. |
284 | | - |
285 | | -To be precise -- they are still asynchronous, but run as soon as possible, similar to `setTimeout(...,0)`. |
286 | | - |
287 | | -For instance, here we'll first see "code end", and then "done!": |
| 247 | +For instance, here we'll first see "code end" `(1)`, and then "done!" `(2)`: |
288 | 248 |
|
289 | 249 | ```js run |
290 | | -// the promise is in the "resolved" state immediately |
291 | | -let promise = new Promise(function(resolve, reject) { |
292 | | - resolve("done!"); |
293 | | -}); |
| 250 | +let promise = new Promise(resolve => resolve("done!")); |
294 | 251 |
|
295 | | -// the handler runs as soon as possible, but asynchronously, like setTimeout(...,0) |
296 | | -promise.then(alert); |
| 252 | +// alert runs as soon as possible, but asynchronously, |
| 253 | +// like if it were wrapped in setTimeout(..., 0); |
| 254 | +promise.then(alert); // (2) |
297 | 255 |
|
298 | | -alert('code end'); |
| 256 | +alert('code end'); // (1) |
299 | 257 | ``` |
300 | 258 |
|
301 | 259 | ```` |
302 | 260 |
|
303 | | -````smart header="Functions resolve/reject have only one argument" |
| 261 | +````smart header="Functions resolve/reject accept at most one argument" |
304 | 262 | Functions `resolve/reject` accept only one argument. |
305 | 263 |
|
306 | | -We can call them without any arguments too. The call `resolve()` makes the result `undefined`: |
| 264 | +We can call them without any arguments too, that's the same as passing `undefined`: |
307 | 265 |
|
308 | 266 | ```js run |
309 | | -let promise = new Promise(function(resolve, reject) { |
310 | | - resolve(); |
311 | | -}); |
| 267 | +let promise = new Promise(resolve => resolve()); |
312 | 268 |
|
313 | | -promise.then(result => alert(result)); // undefined |
| 269 | +promise.then(alert); // undefined |
314 | 270 | ``` |
315 | 271 |
|
316 | | -...But if we pass many arguments: `resolve(1, 2, 3)`, then all arguments after the first one are ignored. A promise may have only one value as a result/error. |
317 | | -
|
318 | | -Use objects and destructuring if you need to pass many values, like this: |
| 272 | +...But if we pass many arguments: `resolve(1, 2, 3)`, then all arguments after the first one are ignored. |
| 273 | +The idea is that a promise may have only one result (or an error). Use objects and destructuring if you need to pass many values, like this: |
319 | 274 |
|
320 | 275 | ```js run |
321 | 276 | let promise = new Promise(function(resolve, reject) { |
|
0 commit comments