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
The`fetch`method allows to track *download* progress.
4
+
Metoda`fetch`pozwala śledzić postęp pobierania (ang. *download*).
5
5
6
-
Please note: there's currently no way for `fetch` to track *upload* progress. For that purpose, please use[XMLHttpRequest](info:xmlhttprequest), we'll cover it later.
6
+
Należy pamiętać, że `fetch` nie ma możliwości śledzenia postępu wysyłania danych (ang. *upload*). Do tego celu należy użyć[XMLHttpRequest](info:xmlhttprequest). Omówimy to w dalszej części.
7
7
8
-
To track download progress, we can use `response.body` property. It's `ReadableStream`-- a special object that provides body chunk-by-chunk, as it comes. Readable streams are described in the [Streams API](https://streams.spec.whatwg.org/#rs-class) specification.
8
+
W celu śledzenia postępu pobierania możemy wykorzystać właściwość `response.body`. Jest to specjalny obiekt `ReadableStream`(pol. *odczytywalny strumień*), który udostępnia ciało odpowiedzi na bieżąco, kawałek po kawałku (ang. *chunk*). Odczytywalne strumienie zostały opisane w specyfikacji [API Strumieni](https://streams.spec.whatwg.org/#rs-class).
9
9
10
-
Unlike `response.text()`, `response.json()`and other methods, `response.body`gives full control over the reading process, and we can count how much is consumed at any moment.
10
+
W przeciwieństwie do `response.text()`, `response.json()`czy innych metod, `response.body`pozwala na całkowitą kontrolę nad procesem odczytu, co pozwala na określenie, jaka ilość danych jest zużywana w dowolnym momencie.
11
11
12
-
Here's the sketch of code that reads the reponse from`response.body`:
12
+
Oto przykład kodu, który odczytuje odpowiedź z`response.body`:
13
13
14
14
```js
15
-
//instead of response.json() and other methods
15
+
//zamiast response.json() i innych metod
16
16
constreader=response.body.getReader();
17
17
18
-
//infinite loop while the body is downloading
18
+
//pętla nieskończona w momencie pobierania ciała odpowiedzi
19
19
while(true) {
20
-
// done is true for the last chunk
21
-
// value is Uint8Array of the chunk bytes
20
+
// done przyjmuje wartość true dla ostatniego kawałka
21
+
// value jest tablicą Uint8Array bajtów danego kawałka
22
22
const {done, value} =awaitreader.read();
23
23
24
24
if (done) {
25
25
break;
26
26
}
27
27
28
-
console.log(`Received${value.length}bytes`)
28
+
console.log(`Pobrano${value.length}bajtów`)
29
29
}
30
30
```
31
31
32
-
The result of `await reader.read()`call is an object with two properties:
33
-
-**`done`** -- `true`when the reading is complete, otherwise`false`.
34
-
-**`value`** -- a typed array of bytes:`Uint8Array`.
32
+
Rezultatem wywołania `await reader.read()`jest obiekt, posiadający dwie właściwości:
33
+
-**`done`** -- `true`po zakończeniu odczytu, w przeciwnym przypadku`false`.
Streams API also describes asynchronous iteration over `ReadableStream` with `for await..of` loop, but it's not yet widely supported (see [browser issues](https://github.com/whatwg/streams/issues/778#issuecomment-461341033)), so we use `while` loop.
37
+
Specyfikacja API strumieni opisuje też asynchroniczną iterację po `ReadableStream` za pomocą pętli `for await..of`, aczkolwiek to rozwiązanie nie jest szeroko wspierane (zob. [problemy z przeglądarką](https://github.com/whatwg/streams/issues/778#issuecomment-461341033)), wobec tego użyliśmy pętli `while`.
38
38
```
39
39
40
-
We receive response chunks in the loop, until the loading finishes, that is: until`done`becomes`true`.
40
+
Otrzymujemy kawałki odpowiedzi w pętli, aż do zakończenia ładowania, to znaczy dopóki`done`nie stanie się`true`.
41
41
42
-
To log the progress, we just need for every received fragment `value`to add its length to the counter.
42
+
Aby rejestrować postęp, wystarczy dodawać do licznika długość tablicy `value`każdego otrzymanego kawałka.
43
43
44
-
Here's the full working example that gets the response and logs the progress in console, more explanations to follow:
44
+
Oto w pełni działający przykład, w którym postęp otrzymywanej odpowiedzi jest wyświetlany w konsoli. Szczegóły w dalszej części artykułu.
45
45
46
46
```js run async
47
-
//Step 1: start the fetch and obtain a reader
47
+
//Krok 1: Uruchom pobieranie i uzyskaj obiekt czytający
48
48
let response =awaitfetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');
//Step 4: concatenate chunks into single Uint8Array
71
+
//Krok 4: Połącz kawałki w jedną tablicę Uint8Array
72
72
let chunksAll =newUint8Array(receivedLength); // (4.1)
73
73
let position =0;
74
74
for(let chunk of chunks) {
75
75
chunksAll.set(chunk, position); // (4.2)
76
76
position +=chunk.length;
77
77
}
78
78
79
-
//Step 5: decode into a string
79
+
//Krok 5: Dekoduj na łańcuch znaków
80
80
let result =newTextDecoder("utf-8").decode(chunksAll);
81
81
82
-
//We're done!
82
+
//Skończone!
83
83
let commits =JSON.parse(result);
84
84
alert(commits[0].author.login);
85
85
```
86
86
87
-
Let's explain that step-by-step:
87
+
Wyjaśnijmy wszystko krok po kroku:
88
88
89
-
1.We perform `fetch`as usual, but instead of calling `response.json()`, we obtain a stream reader`response.body.getReader()`.
89
+
1.Wykonujemy `fetch`jak zazwyczaj, lecz zamiast wywołać `response.json()`, uzyskujemy obiekt czytający strumień za pomocą metody`response.body.getReader()`.
90
90
91
-
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.
92
-
2.Prior to reading, we can figure out the full response length from the `Content-Length` header.
91
+
Zauważ, że nie możemy użyć obu powyższych metod, aby odczytać tę samą odpowiedź: albo więc użyjemy obiektu czytającego, albo którejś z metod żądania.
92
+
2.Przed odczytem możemy pobrać długość pełnej odpowiedzi z nagłówka `Content-Length`.
93
93
94
-
It may be absent for cross-origin requests (see chapter <info:fetch-crossorigin>) and, well, technically a server doesn't have to set it. But usually it's at place.
95
-
3.Call`await reader.read()`until it's done.
94
+
Może go nie być w przypadku żądań `cross-origin` (patrz rozdział pt. "<info:fetch-crossorigin>") i, technicznie rzecz biorąc, serwer nie musi go ustawiać, aczkolwiek zazwyczaj jest dostępny.
95
+
3.Wywołujemy`await reader.read()`aż do zakończenia odczytu.
96
96
97
-
We gather response chunks in the array `chunks`. 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).
98
-
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:
99
-
1.We create `chunksAll = new Uint8Array(receivedLength)` -- a same-typed array with the combined length.
100
-
2.Then use `.set(chunk, position)` method to copy each `chunk` one after another in it.
101
-
5.We have the result in `chunksAll`. It's a byte array though, not a string.
97
+
Gromadzimy kawałki odpowiedzi w tablicy `chunks`. Jest to istotne, ponieważ po zużyciu odpowiedzi nie będziemy mogli odczytać jej ponownie za pomocą `response.json()`ani w żaden inny sposób (możesz spróbować - pojawi się błąd).
98
+
4.Mamy więc `chunks` -- tablicę zawierającą kawałki odpowiedzi w formacie `Uint8Array`. Musimy je połączyć w jeden wynik. Niestety, nie ma jednej metody, która by je łączyła, potrzebujemy więc nieco kodu, aby to zrobić:
99
+
1.Tworzymy `chunksAll = new Uint8Array(receivedLength)` -- tablicę tego samego typu o łącznym rozmiarze wszystkich kawałków.
100
+
2.Następnie kopiujemy do niej kawałki jeden po drugim używając metody `.set(chunk, position)`.
101
+
5.Wynik trzymamy w zmiennej `chunksAll`. Jest to jednak tablica bajtów, a nie łańcuch znaków.
102
102
103
-
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, if necessary.
103
+
Aby utworzyć ciąg znaków, musimy odpowiednio zinterpretować te bajty. Z pomocą przychodzi nam wbudowana konstruktor [TextDecoder](info:text-decoder). Następnie wywołujemy `JSON.parse`, jeżeli zachodzi taka potrzeba.
104
104
105
-
What if we need binary content instead of a string? That's even simpler. Replace steps 4 and 5 with a single line that creates a `Blob`from all chunks:
105
+
Co jeśli potrzebujemy zawartości binarnej, a nie łańcucha znaków? W takim przypadku sprawa jest jeszcze prostsza. Zastępujemy krok czwarty oraz piąty jedną linijką kodu, który tworzy `Blob`z wszystkich kawałków:
106
106
```js
107
107
let blob =newBlob(chunks);
108
108
```
109
109
110
-
At we end we have the result (as a string or a blob, whatever is convenient), and progress-tracking in the process.
110
+
W rezultacie otrzymujemy łańcuch znaków lub `Blob` (w zależności od potrzeb) oraz możliwość śledzenia postępu całego procesu.
111
111
112
-
Once again, please note, that's not for *upload* progress (no way now with `fetch`), only for *download* progress.
112
+
Ważne, aby pamiętać, że powyższe nie dotyczy postępu *wysyłania* (obecnie niemożliwe za pomocą`fetch`), a jedynie postępu *pobierania* danych.
0 commit comments