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
`Fetch`allows to track download progress, but not upload progress.
4
+
`Fetch`позволяет отслеживать процесс получения данных.
5
5
6
-
Please note: there's currently no way for fetch to track upload progress. For that purpose, please use[XMLHttpRequest](info:xmlhttprequest).
6
+
Заметим, на данный момент в `fetch` нет способа отследить прогресс отправки данных. Для этого используйте[XMLHttpRequest](info:xmlhttprequest).
7
7
8
-
To track download progress, we can use`response.body` property. It's a "readable stream" -- a special object that provides body chunk-by-chunk, as it comes, so we can see how much is available at the moment.
8
+
Если мы хотим отследить ход загрузки данных с сервера, можно использовать свойство`response.body`. Это так называемый "поток для чтения" (англ. `readable stream`) -- особый объект, который предоставляет тело ответа по частям, по мере поступления, так что мы можем увидеть, сколько уже получено.
9
9
10
-
Here's the sketch of code that uses it to read response:
10
+
Вот пример кода, который использует этот объект для чтения ответа:
11
11
12
12
```js
13
-
//instead of response.json() and other methods
13
+
//вместо response.json() и других методов
14
14
constreader=response.body.getReader();
15
15
16
-
//infinite loop while the body is downloading
16
+
//бесконечный цикл, пока идёт загрузка
17
17
while(true) {
18
-
// done is true for the last chunk
19
-
// value is Uint8Array of the chunk bytes
18
+
// done становится true в последнем фрагменте
19
+
// value - Uint8Array из байтов каждого фрагмента
20
20
const {done, value} =awaitreader.read();
21
21
22
22
if (done) {
23
23
break;
24
24
}
25
25
26
-
console.log(`Received${value.length}bytes`)
26
+
console.log(`Получено${value.length}байт`)
27
27
}
28
28
```
29
29
30
-
So, we loop, while`await reader.read()`returns response chunks.
30
+
Таким образом, цикл идёт, пока`await reader.read()`возвращает в ответе данные по частям.
31
31
32
-
A chunk has two properties:
33
-
-**`done`** -- true when the reading is complete.
34
-
-**`value`** -- a typed array of bytes: `Uint8Array`.
32
+
У возвращаемого фрагмента (англ. `chunk`) есть два свойства:
//Step 4: concatenate chunks into single Uint8Array
65
+
//Шаг 4: соединим фрагменты в общий типизированный массив Uint8Array
66
66
let chunksAll =newUint8Array(receivedLength); // (4.1)
67
67
let position =0;
68
68
for(let chunk of chunks) {
69
69
chunksAll.set(chunk, position); // (4.2)
70
70
position +=chunk.length;
71
71
}
72
72
73
-
//Step 5: decode into a string
73
+
//Шаг 5: декодируем Uint8Array обратно в строку
74
74
let result =newTextDecoder("utf-8").decode(chunksAll);
75
75
76
-
//We're done!
76
+
//Готово!
77
77
let commits =JSON.parse(result);
78
78
alert(commits[0].author.login);
79
79
```
80
80
81
-
Let's explain that step-by-step:
81
+
Разберёмся, что здесь произошло:
82
82
83
-
1.We perform `fetch`as usual, but instead of calling `response.json()`, we obtain a stream reader`response.body.getReader()`.
83
+
1.Мы обращаемся к `fetch`как обычно, но вместо вызова `response.json()` мы получаем доступ к потоку чтения`response.body.getReader()`.
84
84
85
-
Please note, we can't use both these methods to read the same response. Either use a reader or a response method to get the result.
86
-
2.Prior to reading, we can figure out the full response length from the `Content-Length` header.
85
+
Обратите внимание, что мы не можем использовать одновременно оба эти метода для одного и того же ответа. Используйте либо обычный метод `response.json()`, либо чтение потока `response.body`.
86
+
2.Ещё до чтения потока мы можем вычислить полную длину ответа из заголовка `Content-Length`.
87
87
88
-
It may be absent for cross-domain requests (see chapter <info:fetch-crossorigin>) and, well, technically a server doesn't have to set it. But usually it's at place.
89
-
3.Call`await reader.read()`until it's done.
88
+
Она может отсутствовать в кросс-доменных запросах (подробнее в разделе <info:fetch-crossorigin>) и, в общем-то, серверу необязательно её устанавливать. Тем не менее, обычно длина указана.
89
+
3.Вызываем`await reader.read()`до окончания загрузки.
90
90
91
-
We gather response `chunks` in the array. That's important, because after the response is consumed, we won't be able to "re-read" it using`response.json()`or another way (you can try, there'll be an error).
92
-
4.At the end, we have `chunks`-- an array of `Uint8Array` byte chunks. We need to join them into a single result. Unfortunately, there's no single method that concatenates those, so there's some code to do that:
93
-
1.We create `new Uint8Array(receivedLength)` -- a same-typed array with the combined length.
94
-
2.Then use `.set(chunk, position)`method to copy each `chunk` one after another in the resulting array.
95
-
5.We have the result in`chunksAll`. It's a byte array though, not a string.
91
+
Всё, что получили, мы складываем по "кусочкам" в массив. Это важно, потому что после того, как ответ получен, мы уже не сможем "перечитать" его, используя`response.json()`или любой другой способ (попробуйте - будет ошибка).
92
+
4.В самом конце у нас типизированный массив -- `Uint8Array`. В нём находятся фрагменты данных. Нам нужно их склеить, чтобы получить строку. К сожалению, для этого нет специального метода, но можно сделать, например, так:
93
+
1.Создаём `new Uint8Array(receivedLength)` -- массив того же типа заданной длины.
94
+
2.Используем `.set(chunk, position)`метод для копирования каждого фрагмента друг за другом в массив результатов.
95
+
5.Наш результат теперь хранится в`chunksAll`. Это не строка, а байтовый массив.
96
96
97
-
To create a string, we need to interpret these bytes. The built-in[TextDecoder](info:text-decoder)does exactly that. Then we can `JSON.parse` it.
97
+
Чтобы получить именно строку, надо декодировать байты. Встроенный метод[TextDecoder](info:text-decoder)как раз этим и занимается. Потом мы можем распарсить её с помощью `JSON.parse`.
98
98
99
-
What if we need binary content instead of JSON? That's even simpler. Instead of steps 4 and 5, we could make a blob of all chunks:
99
+
Что если результат нам нужен в бинарном виде, а не в JSON-формате? Это ещё проще. Вместо шагов 4 и 5, мы создаём объект `Blob`:
100
100
```js
101
101
let blob =newBlob(chunks);
102
102
```
103
103
104
-
Once again, please note, that's not for upload progress (no way now), only for download progress.
104
+
На всякий случай повторимся, что здесь мы рассмотрели, как отслеживать процесс получения данных с сервера, а не их отправки на сервер. Как отследить отправку `fetch` - пока нет способа.
0 commit comments