minor fixes

This commit is contained in:
Ilya Kantor 2019-07-04 22:21:34 +03:00
parent b1b66a3065
commit 8365ea7163
6 changed files with 22 additions and 22 deletions

View file

@ -31,7 +31,7 @@ alert(phrase); // Error, phrase is not defined
## "var" has no block scope ## "var" has no block scope
`var` variables are either function-wide or global, they are visible through blocks. Variables, declared with `var`, are either function-wide or global. They are visible through blocks.
For instance: For instance:
@ -45,7 +45,7 @@ alert(test); // true, the variable lives after if
*/!* */!*
``` ```
`var` ignores code blocks, so we've got a global variable `test`. As `var` ignores code blocks, we've got a global variable `test`.
If we used `let test` instead of `var test`, then the variable would only be visible inside `if`: If we used `let test` instead of `var test`, then the variable would only be visible inside `if`:

View file

@ -9,7 +9,6 @@ There are two methods for it:
These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.js. These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.js.
## setTimeout ## setTimeout
The syntax: The syntax:
@ -291,9 +290,9 @@ For server-side JavaScript, that limitation does not exist, and there exist othe
- To cancel the execution, we should call `clearInterval/clearTimeout` with the value returned by `setInterval/setTimeout`. - To cancel the execution, we should call `clearInterval/clearTimeout` with the value returned by `setInterval/setTimeout`.
- Nested `setTimeout` calls is a more flexible alternative to `setInterval`. Also they can guarantee the minimal time *between* the executions. - Nested `setTimeout` calls is a more flexible alternative to `setInterval`. Also they can guarantee the minimal time *between* the executions.
- Zero delay scheduling with `setTimeout(func, 0)` (the same as `setTimeout(func)`) is used to schedule the call "as soon as possible, but after the current code is complete". - Zero delay scheduling with `setTimeout(func, 0)` (the same as `setTimeout(func)`) is used to schedule the call "as soon as possible, but after the current code is complete".
- The browsere ensures that for five or more nested call of `setTimeout`, or for zero-delay `setInterval`, the real delay between calls is at least 4ms. That's for historical reasons. - The browser limits the minimal delay for five or more nested call of `setTimeout` or for `setInterval` (after 5th call) to 4ms. That's for historical reasons.
Please note that all scheduling methods do not *guarantee* the exact delay. We should not rely on that in the scheduled code. Please note that all scheduling methods do not *guarantee* the exact delay.
For example, the in-browser timer may slow down for a lot of reasons: For example, the in-browser timer may slow down for a lot of reasons:
- The CPU is overloaded. - The CPU is overloaded.

View file

@ -122,7 +122,7 @@ user.name = "Pete"; // Error: Cannot assign to read only property 'name'...
Now no one can change the name of our user, unless they apply their own `defineProperty` to override ours. Now no one can change the name of our user, unless they apply their own `defineProperty` to override ours.
```smart header="Errors appear only in use strict" ```smart header="Errors appear only in strict mode"
In the non-strict mode, no errors occur when writing to read-only properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict. In the non-strict mode, no errors occur when writing to read-only properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict.
``` ```

View file

@ -112,7 +112,7 @@ Promise.all(requests)
)); ));
``` ```
A bigger example with fetching user information for an array of github users by their names (or we could fetch an array of goods by their ids, the logic is same): A bigger example with fetching user information for an array of GitHub users by their names (we could fetch an array of goods by their ids, the logic is same):
```js run ```js run
let names = ['iliakan', 'remy', 'jeresig']; let names = ['iliakan', 'remy', 'jeresig'];
@ -134,7 +134,7 @@ Promise.all(requests)
.then(users => users.forEach(user => alert(user.name))); .then(users => users.forEach(user => alert(user.name)));
``` ```
**If any of the promises is rejected, `Promise.all` immediately rejects with that error.** **If any of the promises is rejected, the promise returned by `Promise.all` immediately rejects with that error.**
For instance: For instance:
@ -155,10 +155,10 @@ If one promise rejects, `Promise.all` immediately rejects, completely forgetting
For example, if there are multiple `fetch` calls, like in the example above, and one fails, other ones will still continue to execute, but `Promise.all` don't watch them any more. They will probably settle, but the result will be ignored. For example, if there are multiple `fetch` calls, like in the example above, and one fails, other ones will still continue to execute, but `Promise.all` don't watch them any more. They will probably settle, but the result will be ignored.
`Promise.all` does nothing to cancel them, as there's no concept of "cancellation" in promises. In [another chapter](fetch-abort) we'll cover `AbortController` that aims to help with that, but it's not a part of the Promise API. `Promise.all` does nothing to cancel them, as there's no concept of "cancellation" in promises. In [another chapter](info:fetch-abort) we'll cover `AbortController` that can help with that, but it's not a part of the Promise API.
``` ```
````smart header="`Promise.all(...)` allows non-promise items in `iterable`" ````smart header="`Promise.all(iterable)` allows non-promise \"regular\" values in `iterable`"
Normally, `Promise.all(...)` accepts an iterable (in most cases an array) of promises. But if any of those objects is not a promise, it's wrapped in `Promise.resolve`. Normally, `Promise.all(...)` accepts an iterable (in most cases an array) of promises. But if any of those objects is not a promise, it's wrapped in `Promise.resolve`.
For instance, here the results are `[1, 2, 3]`: For instance, here the results are `[1, 2, 3]`:
@ -173,8 +173,7 @@ Promise.all([
]).then(alert); // 1, 2, 3 ]).then(alert); // 1, 2, 3
``` ```
So we are able to pass non-promise values to `Promise.all` where convenient. So we are able to pass ready values to `Promise.all` where convenient.
```` ````
## Promise.allSettled ## Promise.allSettled
@ -289,4 +288,4 @@ There are 5 static methods of `Promise` class:
- `value` (if fulfilled) or `reason` (if rejected). - `value` (if fulfilled) or `reason` (if rejected).
5. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome. 5. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome.
Of these five, `Promise.all/allSettled` are the most common in practice. Of these five, `Promise.all` is probably the most common in practice.

View file

@ -21,7 +21,7 @@ That's strange, because the promise is definitely done from the beginning.
Why did the `.then` trigger afterwards? What's going on? Why did the `.then` trigger afterwards? What's going on?
## Microtasks ## Microtasks queue
Asynchronous tasks need proper management. For that, the standard specifies an internal queue `PromiseJobs`, more often referred to as "microtask queue" (v8 term). Asynchronous tasks need proper management. For that, the standard specifies an internal queue `PromiseJobs`, more often referred to as "microtask queue" (v8 term).
@ -68,7 +68,7 @@ let promise = Promise.reject(new Error("Promise Failed!"));
promise.catch(err => alert('caught')); promise.catch(err => alert('caught'));
*/!* */!*
// no error, all quiet // doesn't run: error handled
window.addEventListener('unhandledrejection', event => alert(event.reason)); window.addEventListener('unhandledrejection', event => alert(event.reason));
``` ```
@ -95,11 +95,11 @@ window.addEventListener('unhandledrejection', event => alert(event.reason));
Now, if you run it, we'll see `Promise Failed!` message first, and then `caught`. Now, if you run it, we'll see `Promise Failed!` message first, and then `caught`.
If we didn't know about microtasks, we could wonder: "Why did `unhandledrejection` happen? We did catch the error!". If we didn't know about microtasks queue, we could wonder: "Why did `unhandledrejection` handler run? We did catch the error!".
But now we do know that `unhandledrejection` is generated when the microtask queue is complete: the engine examines promises and, if any of them is in "rejected" state, then the event triggers. But now we understand that `unhandledrejection` is generated when the microtask queue is complete: the engine examines promises and, if any of them is in "rejected" state, then the event triggers.
...By the way, the `.catch` added by `setTimeout` also triggers, of course it does, but later, after `unhandledrejection` has already occurred. In the example above, `.catch` added by `setTimeout` also triggers, but later, after `unhandledrejection` has already occurred, so that doesn't change anything.
## Summary ## Summary

View file

@ -39,7 +39,9 @@ So, without scrollbar the content width would be `300px`, but if the scrollbar i
``` ```
```smart header="The `padding-bottom` area may be filled with text" ```smart header="The `padding-bottom` area may be filled with text"
Usually paddings are shown empty on illustrations, but if there's a lot of text in the element and it overflows, then browsers show the "overflowing" text at `padding-bottom`, so you can see that in examples. Still, the padding is set in further examples, unless explicitly specified otherwise. Usually paddings are shown empty on illustrations, but if there's a lot of text in the element and it overflows, then browsers show the "overflowing" text at `padding-bottom`.
That's a note to avoid confusion, as `padding-bottom` is set in further examples, unless explicitly specified otherwise.
``` ```
## Geometry ## Geometry
@ -66,7 +68,7 @@ That's the nearest ancestor, that satisfies following conditions:
2. or `<td>`, `<th>`, `<table>`, 2. or `<td>`, `<th>`, `<table>`,
2. or `<body>`. 2. or `<body>`.
In most practical cases `offsetParent` is exactly the nearest ancestor, that is CSS-positioned. And `offsetLeft/offsetTop` provide x/y coordinates relative to its upper-left corner. Properties `offsetLeft/offsetTop` provide x/y coordinates relative to its upper-left corner.
In the example below the inner `<div>` has `<main>` as `offsetParent` and `offsetLeft/offsetTop` shifts from its upper-left corner (`180`): In the example below the inner `<div>` has `<main>` as `offsetParent` and `offsetLeft/offsetTop` shifts from its upper-left corner (`180`):
@ -105,7 +107,7 @@ For our sample element:
- `offsetWidth = 390` -- the outer width, can be calculated as inner CSS-width (`300px`) plus paddings (`2 * 20px`) and borders (`2 * 25px`). - `offsetWidth = 390` -- the outer width, can be calculated as inner CSS-width (`300px`) plus paddings (`2 * 20px`) and borders (`2 * 25px`).
- `offsetHeight = 290` -- the outer height. - `offsetHeight = 290` -- the outer height.
````smart header="Geometry properties for not displayed elements are zero/null" ````smart header="Geometry properties are zero/null for elements that are not displayed"
Geometry properties are calculated only for displayed elements. Geometry properties are calculated only for displayed elements.
If an element (or any of its ancestors) has `display:none` or is not in the document, then all geometry properties are zero (or `null` if that's `offsetParent`). If an element (or any of its ancestors) has `display:none` or is not in the document, then all geometry properties are zero (or `null` if that's `offsetParent`).