You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Подобные ситуации случаются очень редко, так как `undefined` обычно явно не присваивается. Для "неизвестных" или "пустых" свойств мы используем значение `null`. Таким образом, оператор `in` является экзотическим гостем в коде.
378
380
379
-
## Цикл "for..in"
381
+
## Цикл "for..in" [#forin]
380
382
381
383
Для перебора всех свойств объекта используется цикл `for..in`. Этот цикл отличается от изученного ранее цикла `for(;;)`.
Copy file name to clipboardExpand all lines: 1-js/11-async/02-promise-basics/article.md
+45-19Lines changed: 45 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,4 @@
1
+
1
2
# Промисы
2
3
3
4
Представьте, что вы известный певец, которого фанаты постоянно донимают расспросами о предстоящем сингле.
@@ -126,9 +127,9 @@ let promise = new Promise(function(resolve, reject) {
126
127
Свойства `state` и `result` - это внутренние свойства объекта `Promise` и мы не имеем к ним прямого доступа. Для обработки результата следует использовать методы `.then`/`.catch`/`.finally`, про них речь пойдёт дальше.
127
128
```
128
129
129
-
## Потребители: then, catch, finally
130
+
## Потребители: then, catch
130
131
131
-
Объект `Promise` служит связующим звеном между исполнителем ("создающим" кодом или "певцом") и функциями-потребителями ("фанатами"), которые получат либо результат, либо ошибку. Функции-потребители могут быть зарегистрированы (подписаны) с помощью методов `.then`, `.catch` и `.finally`.
132
+
Объект `Promise` служит связующим звеном между исполнителем ("создающим" кодом или "певцом") и функциями-потребителями ("фанатами"), которые получат либо результат, либо ошибку. Функции-потребители могут быть зарегистрированы (подписаны) с помощью методов `.then`и `.catch`.
132
133
133
134
### then
134
135
@@ -210,59 +211,84 @@ promise.catch(alert); // выведет "Error: Ошибка!" спустя од
210
211
211
212
Вызов `.catch(f)` - это сокращённый, "укороченный" вариант `.then(null, f)`.
212
213
213
-
### finally
214
+
## Очистка: finally
214
215
215
216
По аналогии с блоком `finally` из обычного `try {...} catch {...}`, у промисов также есть метод `finally`.
216
217
217
218
Вызов `.finally(f)` похож на `.then(f, f)`, в том смысле, что `f` выполнится в любом случае, когда промис завершится: успешно или с ошибкой.
218
219
219
-
`finally` хорошо подходит для очистки, например остановки индикатора загрузки, его ведь нужно остановить вне зависимости от результата.
220
+
Идея `finally` состоит в том, чтобы настроить обработчик для выполнения очистки/доведения после завершения предыдущих операций.
221
+
222
+
Например, остановка индикаторов загрузки, закрытие больше не нужных соединений и т.д.
220
223
221
-
Например:
224
+
Думайте об этом как о завершении вечеринки. Независимо от того, была ли вечеринка хорошей или плохой, сколько на ней было друзей, нам все равно нужно (или, по крайней мере, мы должны) сделать уборку после нее.
225
+
226
+
Код может выглядеть следующим образом:
222
227
223
228
```js
224
229
new Promise((resolve, reject) => {
225
-
/* сделать что-то, что займёт время, и после вызвать resolve/reject */
230
+
/* сделать что-то, что займёт время, и после вызвать resolve или может reject */
226
231
})
227
232
*!*
228
233
// выполнится, когда промис завершится, независимо от того, успешно или нет
229
234
.finally(() => остановить индикатор загрузки)
235
+
// таким образом, индикатор загрузки всегда останавливается, прежде чем мы продолжим
Но это не совсем псевдоним `then(f,f)`, как можно было подумать. Существует несколько важных отличий:
240
+
Обратите внимание, что `finally(f)` - это не совсем псевдоним `then(f,f)`, как можно было подумать.
241
+
242
+
Есть важные различия:
235
243
236
244
1. Обработчик, вызываемый из `finally`, не имеет аргументов. В `finally` мы не знаем, как был завершён промис. И это нормально, потому что обычно наша задача - выполнить "общие" завершающие процедуры.
245
+
246
+
Пожалуйста, взгляните на приведенный выше пример: как вы можете видеть, обработчик `finally` не имеет аргументов, а результат promise обрабатывается в следующем обработчике.
247
+
237
248
2. Обработчик `finally` "пропускает" результат или ошибку дальше, к последующим обработчикам.
238
249
239
250
Например, здесь результат проходит через `finally` к `then`:
251
+
240
252
```js run
241
253
new Promise((resolve, reject) => {
242
-
setTimeout(() => resolve("result"), 2000)
254
+
setTimeout(() => resolve("value"), 2000);
243
255
})
244
-
.finally(() => alert("Промис завершён"))
245
-
.then(result => alert(result)); // <-- .then обработает результат
256
+
.finally(() => alert("Промис завершён")) // срабатывает первым
257
+
.then(result => alert(result)); // <-- .then показывает "value"
246
258
```
247
-
259
+
260
+
Как вы можете видеть, значение возвращаемое первым промисом, передается через `finally` к следующему `then`.
261
+
262
+
Это очень удобно, потому что `finally` не предназначен для обработки результата промиса. Как уже было сказано, это место для проведения общей очистки, независимо от того, каков был результат.
263
+
248
264
А здесь ошибка из промиса проходит через `finally` к `catch`:
249
265
250
266
```js run
251
267
new Promise((resolve, reject) => {
252
268
throw new Error("error");
253
269
})
254
-
.finally(() => alert("Промис завершён"))
255
-
.catch(err => alert(err)); // <-- .catch обработает объект ошибки
270
+
.finally(() => alert("Промис завершён")) // срабатывает первым
271
+
.catch(err => alert(err)); // <-- .catch показывает ошибку
256
272
```
257
273
258
-
Это очень удобно, потому что `finally` не предназначен для обработки результата промиса. Так что он просто пропускает его через себя дальше.
274
+
3. Обработчик `finally` также не должен ничего возвращать. Если это так, то возвращаемое значение молча игнорируется.
259
275
260
-
Мы более подробно поговорим о создании цепочек промисов и передаче результатов между обработчиками в следующей главе.
276
+
Единственным исключением из этого правила является случай, когда обработчик `finally` выдает ошибку. Затем эта ошибка передается следующему обработчику вместо любого предыдущего результата.
277
+
278
+
Подведем итог:
261
279
262
-
3. Последнее, но не менее значимое: вызов `.finally(f)` удобнее, чем `.then(f, f)` - не надо дублировать функции f.
280
+
- Обработчик `finally` не получает результат предыдущего обработчика (у него нет аргументов). Вместо этого этот результат передается следующему подходящему обработчику.
281
+
- Если обработчик `finally` возвращает что-то, это игнорируется.
282
+
- Когда `finally` выдает ошибку, выполнение переходит к ближайшему обработчику ошибок.
283
+
284
+
Эти функции полезны и заставляют все работать правильно, если мы используем `finally` так, как предполагается: для общих процедур очистки.
Если промис в состоянии ожидания, обработчики в `.then/catch/finally` будут ждать его. Однако, если промис уже завершён, то обработчики выполнятся сразу:
287
+
Если промис в состоянии ожидания, обработчики в `.then/catch/finally` будут ждать его.
288
+
289
+
Иногда может случиться так, что промис уже выполнен, когда мы добавляем к нему обработчик.
290
+
291
+
В таком случае эти обработчики просто запускаются немедленно:
266
292
267
293
```js run
268
294
// при создании промиса он сразу переводится в состояние "успешно завершён"
Copy file name to clipboardExpand all lines: 1-js/11-async/04-promise-error-handling/article.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -199,6 +199,7 @@ new Promise(function() {
199
199
## Итого
200
200
201
201
-`.catch` перехватывает все виды ошибок в промисах: будь то вызов `reject()` или ошибка, брошенная в обработчике при помощи `throw`.
202
+
-`.then` также перехватывает ошибки таким же образом, если задан второй аргумент (который является обработчиком ошибок).
202
203
- Необходимо размещать `.catch` там, где мы хотим обработать ошибки и знаем, как это сделать. Обработчик может проанализировать ошибку (могут быть полезны пользовательские классы ошибок) и пробросить её, если ничего не знает о ней (возможно, это программная ошибка).
203
204
- Можно и совсем не использовать `.catch`, если нет нормального способа восстановиться после ошибки.
204
205
- В любом случае нам следует использовать обработчик события `unhandledrejection` (для браузеров и аналог для других окружений), чтобы отслеживать необработанные ошибки и информировать о них пользователя (и, возможно, наш сервер), благодаря чему наше приложение никогда не будет "просто умирать".
Copy file name to clipboardExpand all lines: 2-ui/4-forms-controls/2-focus-blur/article.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,4 @@
1
+
1
2
# Фокусировка: focus/blur
2
3
3
4
Элемент получает фокус, когда пользователь кликает по нему или использует клавишу `key:Tab`. Также существует HTML-атрибут `autofocus`, который устанавливает фокус на элемент, когда страница загружается. Есть и другие способы получения фокуса, о них - далее.
@@ -51,7 +52,6 @@
51
52
52
53
Современный HTML позволяет делать валидацию с помощью атрибутов `required`, `pattern` и т.д. Иногда - это всё, что нам нужно. JavaScript можно использовать, когда мы хотим больше гибкости. А ещё мы могли бы отправлять изменённое значение на сервер, если оно правильное.
53
54
54
-
55
55
## Методы focus/blur
56
56
57
57
Методы `elem.focus()` и `elem.blur()` устанавливают/снимают фокус.
@@ -90,6 +90,8 @@
90
90
91
91
Отметим, что мы не можем "отменить потерю фокуса", вызвав `event.preventDefault()` в обработчике `onblur` потому, что `onblur` срабатывает *после* потери фокуса элементом.
92
92
93
+
Однако на практике следует хорошо подумать, прежде чем внедрять что-то подобное, потому что мы обычно *должны показывать ошибки* пользователю, но они *не должны мешать* пользователю при заполнении нашей формы. Ведь, вполне возможно, что он захочет сначала заполнить другие поля.
Потеря фокуса может произойти по множеству причин.
95
97
@@ -102,6 +104,7 @@
102
104
103
105
Используя эти события, нужно быть осторожным. Если мы хотим отследить потерю фокуса, которую инициировал пользователь, тогда нам следует избегать её самим.
104
106
```
107
+
105
108
## Включаем фокусировку на любом элементе: tabindex
106
109
107
110
Многие элементы по умолчанию не поддерживают фокусировку.
@@ -125,6 +128,7 @@
125
128
-`tabindex="0"` ставит элемент в один ряд с элементами без `tabindex`. То есть, при переключении такие элементы будут после элементов с `tabindex ≥ 1`.
126
129
127
130
Обычно используется, чтобы включить фокусировку на элементе, но не менять порядок переключения. Чтобы элемент мог участвовать в форме наравне с обычными `<input>`.
131
+
128
132
-`tabindex="-1"` позволяет фокусироваться на элементе только программно. Клавиша `key:Tab` проигнорирует такой элемент, но метод `elem.focus()` будет действовать.
129
133
130
134
Например, список ниже. Кликните первый пункт в списке и нажмите `key:Tab`:
0 commit comments