This commit is contained in:
Ilya Kantor 2019-08-14 12:36:24 +03:00
parent b753823786
commit 39309e6a07
19 changed files with 60 additions and 35 deletions

View file

@ -223,6 +223,30 @@ As calls become more nested, the code becomes deeper and increasingly more diffi
That's sometimes called "callback hell" or "pyramid of doom."
<!--
loadScript('1.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
}
});
}
})
}
});
-->
![](callback-hell.svg)
The "pyramid" of nested calls grows to the right with every asynchronous action. Soon it spirals out of control.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before After
Before After

View file

@ -239,8 +239,8 @@ function* generateSequence(start, end) {
Now we'd like to reuse it for generation of a more complex sequence:
- first, digits `0..9` (with character codes 48..57),
- followed by alphabet letters `a..z` (character codes 65..90)
- followed by uppercased letters `A..Z` (character codes 97..122)
- followed by alphabet letters `A..Z` (character codes 65..90)
- followed by uppercased letters `a..z` (character codes 97..122)
We can use this sequence e.g. to create passwords by selecting characters from it (could add syntax characters as well), but let's generate it first.

View file

@ -283,7 +283,7 @@ for await (let commit of fetchCommits(repo)) {
}
```
We'd like a call, like `fetchCommits(repo)` to get commits for us, making requests whenever needed. And let it care about all pagination stuff, for us it'll be a simple `for await..of`.
We'd like to make a function `fetchCommits(repo)` that gets commits for us, making requests whenever needed. And let it care about all pagination stuff, for us it'll be a simple `for await..of`.
With async generators that's pretty easy to implement:
@ -361,4 +361,4 @@ In web-development we often meet streams of data, when it flows chunk-by-chunk.
We can use async generators to process such data, but it's also worth to mention that there's also another API called Streams, that provides special interfaces to work with such streams, to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere).
Streams API is not a part of JavaScript language standard.
Streams API is not a part of JavaScript language standard.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="659" height="111" viewBox="0 0 659 111"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="binary" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="blob.svg"><path id="Rectangle-227" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M108 56h96v28h-96z"/><text id="image/png" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="113.8" y="74">image/pn</tspan> <tspan x="190.6" y="74" letter-spacing="3">g</tspan></text><path id="Rectangle-227" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M238 56h71v28h-71z"/><text id="blob1" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="250" y="74">blob1</tspan></text><path id="Rectangle-227-Copy" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M308 56h71v28h-71z"/><text id="blob2" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="320" y="74">blob2</tspan></text><path id="Rectangle-227-Copy-3" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M475 56h71v28h-71z"/><text id="str" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="497.1" y="74">str</tspan></text><path id="Rectangle-227-Copy-4" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M546 56h71v28h-71z"/><text id="buffer" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="553.7" y="74">buffer</tspan></text><path id="Rectangle-227-Copy-2" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M379 56h96v28h-96z"/><text id="..." fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="413.1" y="74">...</tspan></text><text id="type" fill="#000" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="135.692" y="24">type</tspan></text><text id="Blob" fill="#000" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="24.823" y="76">Blob</tspan></text><text id="blobParts" fill="#000" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="378.21" y="24">blobParts</tspan></text><text id="+" fill="#D0021B" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="216.782" y="77">+</tspan></text><text id="=" fill="#D0021B" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="77.782" y="77">=</tspan></text><path id="Line-2" stroke="#EE6B47" stroke-linecap="square" stroke-width="2" d="M239 45c81.34-6.667 143.674-10 187-10 43.326 0 105.66 3.333 187 10"/></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="659" height="111" viewBox="0 0 659 111"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="binary" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="blob.svg"><path id="Rectangle-227" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M108 56h96v28h-96z"/><text id="image/png" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="113.3" y="74">image/png</tspan></text><path id="Rectangle-227" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M238 56h71v28h-71z"/><text id="blob1" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="250" y="74">blob1</tspan></text><path id="Rectangle-227-Copy" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M308 56h71v28h-71z"/><text id="blob2" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="320" y="74">blob2</tspan></text><path id="Rectangle-227-Copy-3" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M475 56h71v28h-71z"/><text id="str" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="497.1" y="74">str</tspan></text><path id="Rectangle-227-Copy-4" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M546 56h71v28h-71z"/><text id="buffer" fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="553.7" y="74">buffer</tspan></text><path id="Rectangle-227-Copy-2" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M379 56h96v28h-96z"/><text id="..." fill="#000" font-family="PTMono-Regular, PT Mono" font-size="16" font-weight="normal"><tspan x="413.1" y="74">...</tspan></text><text id="type" fill="#000" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="135.692" y="24">type</tspan></text><text id="Blob" fill="#000" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="24.823" y="76">Blob</tspan></text><text id="blobParts" fill="#000" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="378.21" y="24">blobParts</tspan></text><text id="+" fill="#D0021B" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="216.782" y="77">+</tspan></text><text id="=" fill="#D0021B" font-family="OpenSans-Regular, Open Sans" font-size="20" font-weight="normal"><tspan x="77.782" y="77">=</tspan></text><path id="Line-2" stroke="#EE6B47" stroke-linecap="square" stroke-width="2" d="M239 45c81.34-6.667 143.674-10 187-10 43.326 0 105.66 3.333 187 10"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before After
Before After

View file

@ -6,7 +6,7 @@ Despite of having the word "XML" in its name, it can operate on any data, not on
Right now, there's another, more modern method `fetch`, that somewhat deprecates `XMLHttpRequest`.
In modern web-development `XMLHttpRequest` may be used for three reasons:
In modern web-development `XMLHttpRequest` is used for three reasons:
1. Historical reasons: we need to support existing scripts with `XMLHttpRequest`.
2. We need to support old browsers, and don't want polyfills (e.g. to keep scripts tiny).
@ -51,7 +51,7 @@ To do the request, we need 3 steps:
Some request methods like `GET` do not have a body. And some of them like `POST` use `body` to send the data to the server. We'll see examples later.
4. Listen to events for response.
4. Listen to `xhr` events for response.
These three are the most widely used:
- `load` -- when the result is ready, that includes HTTP errors like 404.
@ -110,7 +110,7 @@ xhr.onerror = function() {
};
```
Once the server has responded, we can receive the result in the following properties of the request object:
Once the server has responded, we can receive the result in the following `xhr` properties:
`status`
: HTTP status code (a number): `200`, `404`, `403` and so on, can be `0` in case of a non-HTTP failure.
@ -119,7 +119,7 @@ Once the server has responded, we can receive the result in the following proper
: HTTP status message (a string): usually `OK` for `200`, `Not Found` for `404`, `Forbidden` for `403` and so on.
`response` (old scripts may use `responseText`)
: The server response.
: The server response body.
We can also specify a timeout using the corresponding property:
@ -130,7 +130,7 @@ xhr.timeout = 10000; // timeout in ms, 10 seconds
If the request does not succeed within the given time, it gets canceled and `timeout` event triggers.
````smart header="URL search parameters"
To pass URL parameters, like `?name=value`, and ensure the proper encoding, we can use [URL](info:url) object:
To add parameters to URL, like `?name=value`, and ensure the proper encoding, we can use [URL](info:url) object:
```js
let url = new URL('https://google.com/search');
@ -208,9 +208,7 @@ xhr.onreadystatechange = function() {
};
```
You can find `readystatechange` listeners in really old code, it's there for historical reasons, as there was a time when there were no `load` and other events.
Nowadays, `load/error/progress` handlers deprecate it.
You can find `readystatechange` listeners in really old code, it's there for historical reasons, as there was a time when there were no `load` and other events. Nowadays, `load/error/progress` handlers deprecate it.
## Aborting request
@ -305,7 +303,7 @@ There are 3 methods for HTTP-headers:
Headers are returned as a single line, e.g.:
```
```http
Cache-Control: max-age=31536000
Content-Length: 4260
Content-Type: image/png
@ -327,6 +325,8 @@ There are 3 methods for HTTP-headers:
result[name] = value;
return result;
}, {});
// headers['Content-Type'] = 'image/png'
```
## POST, FormData
@ -340,14 +340,14 @@ let formData = new FormData([form]); // creates an object, optionally fill from
formData.append(name, value); // appends a field
```
We create it, optionally from a form, `append` more fields if needed, and then:
We create it, optionally fill from a form, `append` more fields if needed, and then:
1. `xhr.open('POST', ...)` use `POST` method.
2. `xhr.send(formData)` to submit the form to the server.
For instance:
```html run
```html run refresh
<form name="person">
<input name="name" value="John">
<input name="surname" value="Smith">
@ -365,6 +365,7 @@ For instance:
xhr.open("POST", "/article/xmlhttprequest/post/user");
xhr.send(formData);
xhr.onload = () => alert(xhr.response);
</script>
```
@ -388,19 +389,19 @@ xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(json);
```
The `.send(body)` method is pretty omnivore. It can send almost everything, including `Blob` and `BufferSource` objects.
The `.send(body)` method is pretty omnivore. It can send almost any `body`, including `Blob` and `BufferSource` objects.
## Upload progress
The `progress` event only works on the downloading stage.
The `progress` event triggers only on the downloading stage.
That is: if we `POST` something, `XMLHttpRequest` first uploads our data (the request body), then downloads the response.
If we're uploading something big, then we're surely more interested in tracking the upload progress. But `xhr.onprogress` doesn't help here.
There's another object `xhr.upload`, without methods, exclusively for upload events.
There's another object, without methods, exclusively to track upload events: `xhr.upload`.
The event list is similar to `xhr` events, but `xhr.upload` triggers them on uploading:
It generates events, similar to `xhr`, but `xhr.upload` triggers them solely on uploading:
- `loadstart` -- upload started.
- `progress` -- triggers periodically during the upload.
@ -519,7 +520,7 @@ There are actually more events, the [modern specification](http://www.w3.org/TR/
The `error`, `abort`, `timeout`, and `load` events are mutually exclusive. Only one of them may happen.
The most used events are load completion (`load`), load failure (`error`), or we can use a single `loadend` handler and check the response to see what happened.
The most used events are load completion (`load`), load failure (`error`), or we can use a single `loadend` handler and check the properties of the request object `xhr` to see what happened.
We've already seen another event: `readystatechange`. Historically, it appeared long ago, before the specification settled. Nowadays, there's no need to use it, we can replace it with newer events, but it can often be found in older scripts.

View file

@ -12,9 +12,9 @@ To resume upload, we need to know how much was uploaded till the connection was
There's `xhr.upload.onprogress` to track upload progress.
Unfortunately, it's useless here, as it triggers when the data is *sent*, but was it received by the server? The browser doesn't know.
Unfortunately, it won't help us to resume the upload here, as it triggers when the data is *sent*, but was it received by the server? The browser doesn't know.
Maybe it was buffered by a local network proxy, or maybe the remote server process just died and couldn't process them, or it was just lost in the middle when the connection broke, and didn't reach the receiver.
Maybe it was buffered by a local network proxy, or maybe the remote server process just died and couldn't process them, or it was just lost in the middle and didn't reach the receiver.
So, this event is only useful to show a nice progress bar.

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="245" height="74" viewBox="0 0 245 74"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="regexp" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="hello-java-boundaries.svg"><text id="Hello,-Java!" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="22" font-weight="normal" letter-spacing="4.583"><tspan x="20" y="61">Hello, Java</tspan> <tspan x="215.617" y="61">!</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M15.5 25.5v-17h2v17h6l-7 14-7-14h6z"/><path id="Line-2" fill="#EE6B47" fill-rule="nonzero" d="M110.5 25.5v-17h2v17h6l-7 14-7-14h6z"/><path id="Line-3" fill="#EE6B47" fill-rule="nonzero" d="M142.5 25.5v-17h2v17h6l-7 14-7-14h6z"/><path id="Line-4" fill="#EE6B47" fill-rule="nonzero" d="M216.5 25.5v-17h2v17h6l-7 14-7-14h6z"/></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="291" height="74" viewBox="0 0 291 74"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="regexp" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="hello-java-boundaries.svg"><text id="H-e-l-l-o,-J-a-v-a!" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="22" font-weight="normal"><tspan x="20" y="61">H e l l o, J a v a!</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M15.5 25.5v-17h2v17h6l-7 14-7-14h6z"/><path id="Line-2" fill="#EE6B47" fill-rule="nonzero" d="M140.5 25.5v-17h2v17h6l-7 14-7-14h6z"/><path id="Line-3" fill="#EE6B47" fill-rule="nonzero" d="M177.5 25.5v-17h2v17h6l-7 14-7-14h6z"/><path id="Line-4" fill="#EE6B47" fill-rule="nonzero" d="M271.5 25.5v-17h2v17h6l-7 14-7-14h6z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="236" height="52" viewBox="0 0 236 52"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="regexp" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1" font-family="PTMono-Regular, PT Mono" font-weight="normal"><g id="love-html5-classes.svg"><text id="I-love-HTML5" fill="#8A704D" font-size="22" letter-spacing="4.583"><tspan x="9" y="39">I love HTML</tspan> <tspan x="204.617" y="39">5</tspan></text><text id="\s-\w-\w-\w-\w-\d" fill="#F38158" font-size="12" letter-spacing="-1.2"><tspan x="114" y="16">\s \w \w \w \w \</tspan> <tspan x="210" y="16">d</tspan></text></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="52" viewBox="0 0 320 52"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="regexp" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1" font-family="PTMono-Regular, PT Mono" font-weight="normal"><g id="love-html5-classes.svg"><text id="I-l-o-v-e-H-T-M-L-5" fill="#8A704D" font-size="22"><tspan x="11" y="39">I l o v e H T M L 5</tspan></text><text id="\w" fill="#F38158" font-size="14"><tspan x="270" y="15">\w</tspan></text><text id="\w-copy" fill="#F38158" font-size="14"><tspan x="244" y="15">\w</tspan></text><text id="\w-copy-2" fill="#F38158" font-size="14"><tspan x="218" y="15">\w</tspan></text><text id="\w-copy-3" fill="#F38158" font-size="14"><tspan x="192" y="15">\w</tspan></text><text id="\s" fill="#F38158" font-size="14"><tspan x="166" y="15">\s</tspan></text><text id="\d" fill="#F38158" font-size="14"><tspan x="297" y="15">\d</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.