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
**In chapter 01-11-03 promise-chaining**
There were few mistakes.
And some of sentences were correct, but they were "unnatural" in Ukrainian and make understanding more difficult.
Copy file name to clipboardExpand all lines: 1-js/11-async/03-promise-chaining/article.md
+24-21Lines changed: 24 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
2
2
# Ланцюжок промісів
3
3
4
-
Повернемося до проблеми, згаданої в розділі <info:callbacks>: у нас є послідовність асинхронних задач, які потрібно виконувати одну за одною — наприклад, завантаження скриптів. Як ми можемо це добре закодувати?
4
+
Повернемося до проблеми, згаданої в розділі <info:callbacks>: у нас є послідовність асинхронних задач, які потрібно виконувати одну за одною — наприклад, завантаження скриптів. Як ми можемо написати код зручно і зрозуміло?
5
5
6
6
Проміси надають кілька способів вирішення подібних задач.
7
7
@@ -46,7 +46,7 @@ new Promise(function(resolve, reject) {
46
46
47
47
Усе це працює тому, що кожний виклик `.then` повертає новий проміс, тому ми можемо викликати наступний `.then` на ньому.
48
48
49
-
Коли обробник повертає значення, воно стає результатом того промісу, тому наступний `.then` викликається з цим значенням.
49
+
Коли обробник повертає значення, воно стає результатом його промісу, тому наступний `.then` викликається з цим значенням.
50
50
51
51
**Класична помилка новачка: технічно ми також можемо додати багато `.then` до одного промісу. Та це не ланцюжок.**
52
52
@@ -72,7 +72,7 @@ promise.then(function(result) {
72
72
});
73
73
```
74
74
75
-
Те, що ми зробили тут -- це додали лише кілька обробників до одного промісу. Вони не передають результат один одному; натомість вони обробляють його самостійно.
75
+
Те, що ми зробили тут -- це просто додали кілька обробників до одного промісу. Вони не передають результат один одному по ланцюжку. Вони кожен по своєму обробляють результат одного і того ж проміса.
76
76
77
77
Ось малюнок (порівняйте його з ланцюжком вище):
78
78
@@ -86,7 +86,7 @@ promise.then(function(result) {
86
86
87
87
Обробник, використанний в `.then(handler)` може створити й повернути проміс.
88
88
89
-
У цьому випадку інші обробники чекають, поки він виконається, а потім отримають його результат.
89
+
У цьому випадку інші обробники чекають, поки він виконається, а потім отримують його результат.
90
90
91
91
Наприклад:
92
92
@@ -120,15 +120,15 @@ new Promise(function(resolve, reject) {
120
120
});
121
121
```
122
122
123
-
Тут перший `.then` показує `1` і повертає `new Promise(…)` у рядку `(*)`. Через одну секунду він вирішується, а результат (аргумент `resolve`, тут це `result * 2`) передається обробнику другого `.then`. Цей обробник знаходиться в рядку `(**)`, він показує `2` і робить те ж саме.
123
+
Тут перший `.then` показує `1` і повертає `new Promise(…)` у рядку `(*)`. Через одну секунду він завершується, а результат (аргумент `resolve`, тут це `result * 2`) передається обробнику другого `.then`. Цей обробник знаходиться в рядку `(**)`, він показує `2` і робить те ж саме.
124
124
125
125
Отже, результат такий же, як і в попередньому прикладі: 1 -> 2 -> 4, але тепер із затримкою в 1 секунду між викликами `alert`.
126
126
127
127
Повернення промісів дозволяє нам будувати ланцюжки асинхронних дій.
128
128
129
129
## Приклад: loadScript
130
130
131
-
Давайте використовувати цю можливість з промісифікацією `loadScript`, визначеною у [попередньому розділі](info:promise-basics#loadscript), щоб завантажувати скрипти один за одним, у послідовності:
131
+
Давайте використовувати цю можливість з промісифікацією `loadScript`, описаною у [попередньому розділі](info:promise-basics#loadscript), щоб завантажувати скрипти один за одним, у послідовності:
Тут кожен виклик `loadScript` повертає проміс, а наступний `.then` запускається, коли він виконується. Потім він ініціює завантаження наступного сценарію. Таким чином, скрипти завантажуються один за одним.
165
+
Тут кожен виклик `loadScript` повертає проміс, а наступний `.then` запускається, коли він виконується. Потім він ініціює завантаження наступного. Таким чином, скрипти завантажуються один за одним.
166
166
167
167
Ми можемо додати більше асинхронних дій до ланцюжка. Зверніть увагу, що код все ще "плоский" — він росте вниз, а не вправо. Немає жодних ознак "піраміди приреченості".
Цей код робить те ж саме: завантажує 3 скрипти послідовно. Але він "росте вправо". Тож у нас та ж проблема, що й з колбеками.
185
185
186
-
Люди, які починають використовувати проміси, іноді не знають про ланцюжок, тому пишуть це так. Як правило, перевага віддається ланцюжкам.
186
+
Люди, які починають використовувати проміси, іноді не знають про ланцюжок, тому пишуть це так. Але зазвичай краще писати "ланцюжками".
187
187
188
-
Іноді нормально писати `.then`відразу, оскільки вкладена функція має доступ до зовнішньої області видимості. У наведеному вище прикладі найбільш вкладений колбек має доступ до всіх змінних `script1`, `script2`, `script3`. Але це швидше виняток, ніж правило.
188
+
Іноді справді буває потреба писати `.then`всередині. Для того, щоб вкладена функція мала доступ до зовнішньої області видимості. У наведеному вище прикладі найбільш вкладений колбек має доступ до всіх змінних `script1`, `script2`, `script3`. Але така потреба це швидше виняток, ніж правило.
189
189
190
190
191
191
````smart header="Thenables"
@@ -216,7 +216,7 @@ new Promise(resolve => resolve(1))
216
216
.then(alert); // показує 2 через 1000 мс
217
217
```
218
218
219
-
JavaScript перевіряє об’єкт, повернутий обробником `.then` у рядку `(*)`: якщо він має викликаний метод з ім’ям `then`, тоді він викликає цей метод, та надає власні функції `resolve`, `reject` як аргументи (подібно виконавцю) і чекає, поки один з них не буде викликаний. У наведеному вище прикладі `resolve(2)` викликається через 1 секунду `(**)`. Потім результат передається далі по ланцюжку.
219
+
JavaScript перевіряє об’єкт, повернутий обробником `.then` у рядку `(*)`: якщо він має придатний до викликання метод з ім’ям `then`, тоді він викликає цей метод, та передає йому власні функції `resolve`, `reject` як аргументи (подібно виконавцю) і чекає, поки один з них не буде викликаний. У наведеному вище прикладі `resolve(2)` викликається через 1 секунду `(**)`. Потім результат передається далі по ланцюжку.
220
220
221
221
Ця функція дозволяє нам інтегрувати власні об’єкти з ланцюжками промісів без успадкування від `Promise`.
Зазначений код робить мережевий запит до `url` і повертає проміс. Проміс розв’язується за допомогою об’єкта`response`, коли віддалений сервер відповідає заголовками, але *до завантаження повної відповіді*.
235
+
Зазначений код робить мережевий запит до `url` і повертає проміс. Цей проміс переходить в стан "fullfilled" і його value стає об'єкт`response` (іншими словами, проміс завершується об'єктом `response`) як тільки-но віддалений сервер присилає заголовки, але ще*до завантаження повної відповіді*.
236
236
237
-
Щоб прочитати повну відповідь, ми повинні викликати метод `response.text()`: він повертає проміс, який виконується, коли повний текст завантажується з віддаленого сервера, і містить цей текст як результат.
237
+
Щоб прочитати повну відповідь, ми повинні викликати метод `response.text()`. Цей метод повертає проміс.
238
+
Цей проміс (який ми отримуємо як результат метода `response.text()`):
239
+
1. Завершується аж тоді, коли з віддаленого сервера завантажується увесь текст, не лише заголовки.
240
+
2. Після завершення він містить той текст в якості результату.
238
241
239
242
Наведений нижче код робить запит до `user.json` і завантажує його текст із сервера:
240
243
241
244
```js run
242
245
fetch('/article/promise-chaining/user.json')
243
-
// .then нижче запускається, коли віддалений сервер відповідає
246
+
// .then нижче запускається, коли віддалений сервер прислав заголовки
244
247
.then(function(response) {
245
-
// response.text() повертає новий проміс, який вирішується з повним текстом відповіді,
246
-
//коли він завантажується
248
+
// response.text() повертає новий проміс, який завершується повним текстом відповіді,
Об’єкт `response`, повернутий із `fetch`, також включає метод `response.json()`, який зчитує віддалені дані у форматі JSON. У нашому випадку це ще зручніше, тож перейдемо до нього.
258
+
Об’єкт `response`, повернутий із `fetch`, також має метод `response.json()`, який парсить отриманий текст і зберігає його у форматі JSON. У нашому випадку він ще зручніший чим метод `response.text()`, тому далі будемо користуватись ним.
256
259
257
260
Ми також будемо використовувати стрілкові функції для стислості:
Код працює; дивіться коментарі щодо деталей. Однак у цьому є потенційна проблема, типова помилка для тих, хто починає використовувати проміси.
293
+
Код працює; дивіться коментарі для деталей. Однак у цьому є потенційна проблема, типова помилка для тих, хто починає використовувати проміси.
291
294
292
295
Подивіться на рядок `(*)`: як ми можемо щось зробити *після* того, як аватар закінчить відображатися і видалиться? Наприклад, ми хотіли б показати форму для редагування цього користувача чи щось інше. Поки що такої можливості немає.
Тобто обробник `.then` у рядку `(*)` тепер повертає `new Promise`, який перейде у стан "виконаний" лише після виклику `resolve(githubUser)` у `setTimeout``(**)`. Наступний `.then` в ланцюжку буде чекати цього.
323
326
324
-
Як хороша практика, асинхронна дія завжди повинна повертати проміс. Це дає можливість планувати дії після нього; навіть якщо ми не плануємо розширювати ланцюжок зараз, можливо, це нам знадобиться пізніше.
327
+
Гарним тоном буде писати код так, щоб асинхронна дія завжди повертала проміс. Це даватиме можливість іншим програмістам після вас планувати наступні дії після тієї асинхронної дії; навіть якщо ми не плануємо розширювати ланцюжок зараз, можливо, це нам знадобиться пізніше.
325
328
326
-
Нарешті, ми можемо розділити код на функції, що можуть бути перевикористані:
329
+
Ну а зараз ми можемо розділити код на функції, що можуть бути перевикористані:
Якщо обробник `.then` (або `catch/finally`, не має різниці) повертає проміс, решта ланцюжка чекає, доки він виконається. Коли це відбувається, його результат (або помилка) передається далі.
365
+
Якщо обробник `.then` (або `catch/finally`, однаково) повертає проміс, решта ланцюжка чекає, доки він виконається. Коли це відбувається, його результат (або помилка) передається далі.
0 commit comments