Skip to content

Commit 0e59e86

Browse files
mitrocjakubdrozdek
mitroc
authored andcommitted
Translate 'Fetch: Download progress' page (#31)
1 parent 54bac9e commit 0e59e86

File tree

2 files changed

+45
-45
lines changed

2 files changed

+45
-45
lines changed
Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,60 @@
11

2-
# Fetch: Download progress
2+
# Fetch: Postęp pobierania
33

4-
The `fetch` method allows to track *download* progress.
4+
Metoda `fetch` pozwala śledzić postęp pobierania (ang. *download*).
55

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.
77

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).
99

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.
1111

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`:
1313

1414
```js
15-
// instead of response.json() and other methods
15+
// zamiast response.json() i innych metod
1616
const reader = response.body.getReader();
1717

18-
// infinite loop while the body is downloading
18+
// pętla nieskończona w momencie pobierania ciała odpowiedzi
1919
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
2222
const {done, value} = await reader.read();
2323

2424
if (done) {
2525
break;
2626
}
2727

28-
console.log(`Received ${value.length} bytes`)
28+
console.log(`Pobrano ${value.length} bajtów`)
2929
}
3030
```
3131

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`.
34+
- **`value`** -- reprezentująca tablicę bajtów typu `Uint8Array`.
3535

3636
```smart
37-
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`.
3838
```
3939

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`.
4141

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.
4343

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.
4545

4646
```js run async
47-
// Step 1: start the fetch and obtain a reader
47+
// Krok 1: Uruchom pobieranie i uzyskaj obiekt czytający
4848
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');
4949

5050
const reader = response.body.getReader();
5151

52-
// Step 2: get total length
52+
// Krok 2: Pobierz całkowitą długość
5353
const contentLength = +response.headers.get('Content-Length');
5454

55-
// Step 3: read the data
56-
let receivedLength = 0; // received that many bytes at the moment
57-
let chunks = []; // array of received binary chunks (comprises the body)
55+
// Krok 3: Odczytaj dane
56+
let receivedLength = 0; // otrzymana liczba bajtów w danym momencie
57+
let chunks = []; // tablica otrzymanych binarnych fragmentów (składają się na ciało)
5858
while(true) {
5959
const {done, value} = await reader.read();
6060

@@ -65,48 +65,48 @@ while(true) {
6565
chunks.push(value);
6666
receivedLength += value.length;
6767

68-
console.log(`Received ${receivedLength} of ${contentLength}`)
68+
console.log(`Pobrano ${receivedLength} z ${contentLength}`)
6969
}
7070

71-
// Step 4: concatenate chunks into single Uint8Array
71+
// Krok 4: Połącz kawałki w jedną tablicę Uint8Array
7272
let chunksAll = new Uint8Array(receivedLength); // (4.1)
7373
let position = 0;
7474
for(let chunk of chunks) {
7575
chunksAll.set(chunk, position); // (4.2)
7676
position += chunk.length;
7777
}
7878

79-
// Step 5: decode into a string
79+
// Krok 5: Dekoduj na łańcuch znaków
8080
let result = new TextDecoder("utf-8").decode(chunksAll);
8181

82-
// We're done!
82+
// Skończone!
8383
let commits = JSON.parse(result);
8484
alert(commits[0].author.login);
8585
```
8686

87-
Let's explain that step-by-step:
87+
Wyjaśnijmy wszystko krok po kroku:
8888

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()`.
9090

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`.
9393

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.
9696

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.
102102

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.
104104

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:
106106
```js
107107
let blob = new Blob(chunks);
108108
```
109109

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.
111111

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.

5-network/03-fetch-progress/progress.view/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!doctype html>
22
<script>
33
(async () {
4-
4+
55
const response = await fetch('long.txt');
66
const reader = response.body.getReader();
77

@@ -12,13 +12,13 @@
1212
const chunk = await reader.read();
1313

1414
if (chunk.done) {
15-
console.log("done!");
15+
console.log("gotowe!");
1616
break;
1717
}
1818

1919
chunks.push(chunk.value);
2020
receivedLength += chunk.value.length;
21-
console.log(`${receivedLength}/${contentLength} received`)
21+
console.log(`otrzymano ${receivedLength}/${contentLength}`)
2222
}
2323

2424

0 commit comments

Comments
 (0)