Skip to content

Commit f8630c2

Browse files
authored
Merge branch 'en' into en
2 parents 6bc029c + 92db884 commit f8630c2

File tree

23 files changed

+404
-109
lines changed

23 files changed

+404
-109
lines changed

1-js/02-first-steps/07-operators/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ counter++;
347347
348348
## Bitwise operators
349349
350-
Bitwise operators treat arguments as 32-bit interger numbers and work on the level on their binary representation.
350+
Bitwise operators treat arguments as 32-bit integer numbers and work on the level of their binary representation.
351351
352352
These operators are not JavaScript-specific. They are supported in most programming languages.
353353
773 Bytes
Loading
405 Bytes
Loading

1-js/03-code-quality/06-polyfills/article.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
# Polyfills
33

4-
The JavaScript language steadily evolves. The new proposals to the language appear regularly, they are analyzed and, if considered worthy, are appended to the list at <https://tc39.github.io/ecma262/> and then progress to the [specification](http://www.ecma-international.org/publications/standards/Ecma-262.htm).
4+
The JavaScript language steadily evolves. New proposals to the language appear regularly, they are analyzed and, if considered worthy, are appended to the list at <https://tc39.github.io/ecma262/> and then progress to the [specification](http://www.ecma-international.org/publications/standards/Ecma-262.htm).
55

6-
Teams behind JavaScript engines have their own ideas about what to implement first. It may decide to implement proposals that are in draft and postpone things that are already in the spec, because they are less interesting or just harder to do.
6+
Teams behind JavaScript engines have their own ideas about what to implement first. They may decide to implement proposals that are in draft and postpone things that are already in the spec, because they are less interesting or just harder to do.
77

88
So it's quite common for an engine to implement only the part of the standard.
99

@@ -23,7 +23,7 @@ Actually, there are two parts in Babel:
2323

2424
2. Second, the polyfill.
2525

26-
The transpiler rewrites the code, so syntax features are covered. But for new functions we need to add a special script that implements them. JavaScript is a highly dynamic language, scripts may not just add new functions, but also modify built-in ones, so that they behave according to the modern standard.
26+
The transpiler rewrites the code, so syntax features are covered. But for new functions we need to write a special script that implements them. JavaScript is a highly dynamic language, scripts may not just add new functions, but also modify built-in ones, so that they behave according to the modern standard.
2727

2828
There's a term "polyfill" for scripts that "fill in" the gap and add missing implementations.
2929

2-ui/1-document/01-browser-environment/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ alert(window.innerHeight); // some number
3535

3636
## Document Object Model (DOM)
3737

38-
The `document` object gives access to a page contents. We can change or create literally anything.
38+
The `document` object gives access to the page content. We can change or create literally anything.
3939

4040
For instance:
4141
```js run

2-ui/2-events/03-event-delegation/3-sort-table/solution.md renamed to 2-ui/2-events/03-event-delegation/3-sortable-table/solution.md

File renamed without changes.

2-ui/2-events/03-event-delegation/3-sort-table/solution.view/index.html renamed to 2-ui/2-events/03-event-delegation/3-sortable-table/solution.view/index.html

File renamed without changes.

2-ui/2-events/03-event-delegation/3-sort-table/source.view/index.html renamed to 2-ui/2-events/03-event-delegation/3-sortable-table/source.view/index.html

File renamed without changes.

2-ui/2-events/03-event-delegation/3-sort-table/task.md renamed to 2-ui/2-events/03-event-delegation/3-sortable-table/task.md

File renamed without changes.

8-async/01-callback-hell/article.md

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,42 @@ Many things that we do in JavaScript are asynchronous. We initiate a process, bu
55

66
The most obvious example is `setTimeout`, but there are others, like making network requests, performing animations and so on.
77

8-
Let's see a couple of examples, so that we can discover a problem, and then solve it using "promises".
9-
108
[cut]
119

1210
## Callbacks
1311

14-
Remember resource load/error events? They are covered in the chapter <info:onload-onerror>.
12+
Consider this function `loadScript(src)` that loads a script:
13+
14+
```js
15+
function loadScript(src) {
16+
let script = document.createElement('script');
17+
script.src = src;
18+
document.head.append(script);
19+
}
20+
```
21+
22+
When the script element is added to the document, the browser loads it and executes. So, the function works.
23+
24+
We can use it like this:
25+
26+
```js
27+
// loads and executes the script
28+
loadScript('/my/script.js');
29+
```
30+
31+
The function is asynchronous: the script starts loading now, but finishes later.
32+
33+
```smart header="Synchronous vs asynchronous"
34+
"Synchonous" and "asynchronous" are general programming terms, not specific to JavaScript.
35+
36+
A *synchronous* action suspends the execution until it's completed. For instance, `alert` and `prompt` are synchronous: the program may not continue until they are finished.
37+
38+
An *asynchronous* action allows the program to continue while it's in progress. For instance, `loadScript` in the example above initiates the script loading, but does not suspend the execution. Other commands may execute while the script is loading.
39+
```
1540

16-
Let's say we want to create a function `loadScript` that loads a script and executes our code afterwards.
41+
As of now, `loadScript` provides no way to track the load end. How can we execute our own code after the script is loaded?
1742

18-
It can look like this:
43+
Let's allow that by adding a custom function as a second argument to `loadScript`, that should execute at that moment:
1944

2045
```js
2146
function loadScript(src, callback) {
@@ -36,25 +61,24 @@ loadScript('/my/script.js', function(script) {
3661
});
3762
```
3863

39-
...And it works, shows `alert` after the script is loaded.
40-
41-
That is called "a callback API". Our function `loadScript` performs an asynchronous task and we can hook on its completion using the callback function.
64+
...And it works, shows the `alert` after the script is loaded.
4265

4366
## Callback in callback
4467

45-
What if we need to load two scripts: one more after the first one?
68+
What if we need to load two scripts sequentially: the first one, and then the second one after it?
4669

47-
We can put another `loadScript` inside the callback, like this:
70+
We can put the second `loadScript` inside the callback, like this:
4871

4972
```js
5073
loadScript('/my/script.js', function(script) {
74+
5175
alert(`Cool, the ${script.src} is loaded, let's load one more`);
5276

77+
*!*
5378
loadScript('/my/script2.js', function(script) {
54-
5579
alert(`Cool, the second script is loaded`);
56-
5780
});
81+
*/!*
5882

5983
});
6084
```
@@ -69,11 +93,11 @@ loadScript('/my/script.js', function(script) {
6993
loadScript('/my/script2.js', function(script) {
7094

7195
if (something) {
72-
loadScript('/my/script3.js', function(script) {
7396
*!*
97+
loadScript('/my/script3.js', function(script) {
7498
// ...continue after all scripts are loaded
75-
*/!*
7699
});
100+
*/!*
77101
}
78102

79103
})
@@ -87,7 +111,7 @@ As you can see, a new asynchronous action means one more nesting level.
87111

88112
In this example we didn't consider errors. What if a script loading failed with an error? Our callback should be able to react on that.
89113

90-
Here's an improved version of `loadScript` that can handle errors:
114+
Here's an improved version of `loadScript` that tracks loading errors:
91115

92116
```js run
93117
function loadScript(src, callback) {
@@ -111,32 +135,34 @@ loadScript('/my/script.js', function(error, script) {
111135
if (error) {
112136
// handle error
113137
} else {
114-
// script loaded, go on
138+
// script loaded successfully
115139
}
116140
});
117141
```
118142

119-
The first argument of `callback` is reserved for errors and the second argument for the successful result. That allows to use a single function to pass both success and failure.
143+
The first argument of `callback` is reserved for errors, and the second argument is for the successful result.
120144

121145
## Pyramid of doom
122146

123-
From the first look it's a viable code. And indeed it is. For one or maybe two nested calls it looks fine.
147+
What we've just seen is called a "callback-based" approach to asynchronous programming. We pass a function, and it should run after the process is complete: with an error or a successful result.
148+
149+
From the first look it's a viable way of asynchronous coding. And indeed it is. For one or maybe two nested calls it looks fine.
124150

125-
But for multiple asynchronous actions that follow one after another...
151+
But for multiple asynchronous actions that follow one after another we'll have a code like this:
126152

127153
```js
128-
loadScript('/my/script1.js', function(error, script) {
154+
loadScript('1.js', function(error, script) {
129155

130156
if (error) {
131157
handleError(error);
132158
} else {
133159
// ...
134-
loadScript('/my/script2.js', function(error, script) {
160+
loadScript('2.js', function(error, script) {
135161
if (error) {
136162
handleError(error);
137163
} else {
138164
// ...
139-
loadScript('/my/script3.js', function(error, script) {
165+
loadScript('3.js', function(error, script) {
140166
if (error) {
141167
handleError(error);
142168
} else {
@@ -153,35 +179,16 @@ loadScript('/my/script1.js', function(error, script) {
153179
```
154180

155181
In the code above:
156-
1. we load `/my/script1.js`, then if there's no error
157-
2. we load `/my/script2.js`, then if there's no error
158-
3. we load `/my/script3.js`, then if there's no error -- do something else `(*)`.
182+
1. We load `1.js`, then if there's no error.
183+
2. We load `2.js`, then if there's no error.
184+
3. We load `3.js`, then if there's no error -- do something else `(*)`.
159185

160-
The nested calls become increasingly more difficult to manage, especially if we add real code instead of `...`, that may include more loops, conditional statements and other usage of loaded scripts.
186+
As calls become more nested, the whole thing becomes increasingly more difficult to manage, especially if we add real code instead of `...`, that may include more loops, conditional statements and other usage of loaded scripts.
161187

162188
That's sometimes called "callback hell" or "pyramid of doom".
163189

164190
![](callback-hell.png)
165191

166-
See? It grows right with every asynchronous action.
167-
168-
Compare that with a "regular" synchronous code.
169-
170-
Just *if* `loadScript` were a regular synchronous function:
171-
172-
```js
173-
try {
174-
// assume we get the result in a synchronous manner, without callbacks
175-
let script = loadScript('/my/script.js');
176-
// ...
177-
let script2 = loadScript('/my/script2.js');
178-
// ...
179-
let script3 = loadScript('/my/script3.js');
180-
} catch(err) {
181-
handleError(err);
182-
}
183-
```
184-
185-
How much cleaner and simpler it is!
192+
The pyramid grows to the right with every asynchronous action. Soon it spirales out of control.
186193

187-
Promises allow to write asynchronous code in a similar way. They are really great at that. Let's study them in the next chapter.
194+
Fortunately, there are ways to evade such pyramids. One of them is using "promises", we'll study them in the next chapters.

0 commit comments

Comments
 (0)