From e8b6c592382a9db9c444976a72f605ecd31bfd52 Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 20:29:53 +0200 Subject: [PATCH 01/12] Translated 'sever.js' --- 5-network/01-fetch/post.view/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/5-network/01-fetch/post.view/server.js b/5-network/01-fetch/post.view/server.js index b55870b2a..b9a2a9bed 100644 --- a/5-network/01-fetch/post.view/server.js +++ b/5-network/01-fetch/post.view/server.js @@ -8,7 +8,7 @@ let router = new Router(); router.post('/user', async (ctx) => { ctx.body = { - message: "User saved." + message: "Zapisano użytkownika." }; }); @@ -17,7 +17,7 @@ router.post('/image', async (ctx) => { limit: '1mb' }); ctx.body = { - message: `Image saved, size:${body.length}.` + message: `Zapisano obraz, rozmiar:${body.length}.` }; }); From 9470b2a3fc5665103a239cce3efefc0a00479fea Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 20:32:07 +0200 Subject: [PATCH 02/12] Translate 'task.md' --- 5-network/01-fetch/01-fetch-users/task.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/5-network/01-fetch/01-fetch-users/task.md b/5-network/01-fetch/01-fetch-users/task.md index 4605b4955..b4ea5f2d4 100644 --- a/5-network/01-fetch/01-fetch-users/task.md +++ b/5-network/01-fetch/01-fetch-users/task.md @@ -1,13 +1,13 @@ -# Fetch users from GitHub +# Pobierz użytkowników z GitHuba -Create an async function `getUsers(names)`, that gets an array of GitHub logins, fetches the users from GitHub and returns an array of GitHub users. +Stwórz asynchroniczną funkcję `getUsers(names)`, która pobiera z GitHuba tablicę z nazwami użytkowników, a następnie zwraca tablicę z odpowiadającymi im użytkownikami. -The GitHub url with user information for the given `USERNAME` is: `https://api.github.com/users/USERNAME`. +Informacje o użytkowniku przypisanym do `USERNAME`, znajdują się pod adresem url: `https://api.github.com/users/USERNAME`. -There's a test example in the sandbox. +W środowisku izolowanym znajduje się przykład testowy. -Important details: +Ważne informacje: -1. There should be one `fetch` request per user. -2. Requests shouldn't wait for each other. So that the data arrives as soon as possible. -3. If any request fails, or if there's no such user, the function should return `null` in the resulting array. +1. Można wykonać tylko jedno żądanie `fetch` o dane użytkownika. +2. Żądania nie powinny na siebie oczekiwać. Chodzi o to, aby dane dotarły jak najszybciej. +3. Jeżeli żądanie się nie powiedzie lub nie będzie użytkownika o podanej nazwie, funkcja powinna zwrócić `null` w tablicy wynikowej. \ No newline at end of file From 27af43f1b8ed8273f4942ccafaec50740a5d779d Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 20:33:47 +0200 Subject: [PATCH 03/12] Translate 'solution' --- 5-network/01-fetch/01-fetch-users/solution.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/5-network/01-fetch/01-fetch-users/solution.md b/5-network/01-fetch/01-fetch-users/solution.md index b8dfb62a2..8afaa86cd 100644 --- a/5-network/01-fetch/01-fetch-users/solution.md +++ b/5-network/01-fetch/01-fetch-users/solution.md @@ -1,11 +1,11 @@ -To fetch a user we need: `fetch('https://api.github.com/users/USERNAME')`. +Aby pobrać użytkownika wykorzystamy: `fetch('https://api.github.com/users/USERNAME')`. -If the response has status `200`, call `.json()` to read the JS object. +Jeżeli odpowiedź zostanie zwrócona ze statusem `200`, wywołamy metodę `.json()`, aby móc odczytać javascriptowy obiekt. -Otherwise, if a `fetch` fails, or the response has non-200 status, we just return `null` in the resulting arrray. +Jeżeli natomiast `fetch` się nie powiedzie lub status odpowiedzi będzie inny niz 200, wówczas w tablicy wynikowej zwracamy po prostu `null`. -So here's the code: +Kod wygląda następująco: ```js demo async function getUsers(names) { @@ -33,8 +33,8 @@ async function getUsers(names) { } ``` -Please note: `.then` call is attached directly to `fetch`, so that when we have the response, it doesn't wait for other fetches, but starts to read `.json()` immediately. +Zauważ, że metoda `.then` jest dołączona bezpośrednio do `fetch`, więc nie czeka ona na kolejne żądania, lecz jak tylko otrzyma odpowiedź, natychmiast odczytuje ją przy użyciu metody `.json()`. -If we used `await Promise.all(names.map(name => fetch(...)))`, and call `.json()` on the results, then it would wait for all fetches to respond. By adding `.json()` directly to each `fetch`, we ensure that individual fetches start reading data as JSON without waiting for each other. +Gdybyśmy jednak użyli `await Promise.all(names.map(name => fetch(...)))` i wywołali metodę `.json()` dopiero na rezultacie, wówczas musiałaby ona czekać, aż wszystkie żądania zwrócą swoje odpowiedzi. Dołączając `.json()` bezpośrednio do każdego zapytania `fetch` możemy być pewni, że pojedyncze zapytania zaczną odczytywać dane jako JSON, bez czekania nawzajem na siebie. -That's an example of how low-level Promise API can still be useful even if we mainly use `async/await`. +Jest to przykład tego, jak przydatne może być niskopoziomowe Promise API, nawet jeżeli głównie korzystamy z `async/await`. \ No newline at end of file From d9a9d017bdda357d66c50c25eb7deb52ccb15eb2 Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 20:35:22 +0200 Subject: [PATCH 04/12] Translate 'test.js' --- 5-network/01-fetch/01-fetch-users/_js.view/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/5-network/01-fetch/01-fetch-users/_js.view/test.js b/5-network/01-fetch/01-fetch-users/_js.view/test.js index 95eaf876e..ed8d03137 100644 --- a/5-network/01-fetch/01-fetch-users/_js.view/test.js +++ b/5-network/01-fetch/01-fetch-users/_js.view/test.js @@ -1,7 +1,7 @@ describe("getUsers", function() { - it("gets users from GitHub", async function() { - let users = await getUsers(['iliakan', 'remy', 'no.such.users']); + it("pobiera użytkowników GitHuba", async function() { + let users = await getUsers(['iliakan', 'remy', 'brak.użytkowników']); assert.equal(users[0].login, 'iliakan'); assert.equal(users[1].login, 'remy'); assert.equal(users[2], null); From 835aaba9d7c31d00e924a777cfc3c3523aa736bd Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 20:36:15 +0200 Subject: [PATCH 05/12] Translated 'source.js' --- 5-network/01-fetch/01-fetch-users/_js.view/source.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/5-network/01-fetch/01-fetch-users/_js.view/source.js b/5-network/01-fetch/01-fetch-users/_js.view/source.js index 0c62e7bb5..4a5d2bbe1 100644 --- a/5-network/01-fetch/01-fetch-users/_js.view/source.js +++ b/5-network/01-fetch/01-fetch-users/_js.view/source.js @@ -1,4 +1,4 @@ async function getUsers(names) { - /* your code */ + /* twój kod */ } From 363bc8e29a28b90d9af9db79d71bd8327d9e51e1 Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 22:23:01 +0200 Subject: [PATCH 06/12] Translated 'article.md' --- 5-network/01-fetch/article.md | 192 +++++++++++++++++----------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/5-network/01-fetch/article.md b/5-network/01-fetch/article.md index 1170042e0..6983abfb5 100644 --- a/5-network/01-fetch/article.md +++ b/5-network/01-fetch/article.md @@ -1,74 +1,74 @@ # Fetch -JavaScript can send network requests to the server and load new information whenever is needed. +Ilekroć jest to potrzebne, JavaScript potrafi wykonywać żądania sieciowe do serwera i pobierać nowe informacje. -For example, we can use a network request to: +Można na przykład użyć zapytania sieciowego do: -- Submit an order, -- Load user information, -- Receive latest updates from the server, -- ...etc. +- złożenia zamówienia, +- wyświetlenia informacji o użytkowniku, +- otrzymania najnowszych aktualizacji z serwera, +- ...itp. -...And all of that without reloading the page! +...I to wszystko bez przeładowania strony! -There's an umbrella term "AJAX" (abbreviated Asynchronous JavaScript And XML) for network requests from JavaScript. We don't have to use XML though: the term comes from old times, that's why that word is there. You may have heard that term already. +Istnieje nadrzędny termin "AJAX" (skrót od Asynchronous JavaScript And XML) dotyczący żądań sieciowych w JavaScript. Nie musimy jednak używać XML-a: skrót ten pochodzi z dawnych czasów, stąd też zawiera takie właśnie słowo. Być może znasz już ten termin. -There are multiple ways to send a network request and get information from the server. +Istnieje wiele sposobów wysłania żądania sieciowego i pobrania informacji z serwera. -The `fetch()` method is modern and versatile, so we'll start with it. It's not supported by old browsers (can be polyfilled), but very well supported among the modern ones. +Metoda `fetch()` jest nowoczesna i wszechstronna, zaczniemy więc od niej. Nie jest ona wspierana przez stare przeglądarki (można ją zaimplementować skryptem typu polyfill), jest natomiast bardzo dobrze obsługiwana przez współczesne przeglądarki. -The basic syntax is: +Podstawowa składnia jest następująca: ```js let promise = fetch(url, [options]) ``` -- **`url`** -- the URL to access. -- **`options`** -- optional parameters: method, headers etc. +- **`url`** -- adres URL zapytania. +- **`options`** -- parametry opcjonalne: metoda, nagłówki, itp. -Without `options`, that is a simple GET request, downloading the contents of the `url`. +Bez `options` mamy do czynienia ze zwykłym zapytaniem GET, pobierającym zawartość adresu `url`. -The browser starts the request right away and returns a promise that the calling code should use to get the result. +Przeglądarka natychmiast uruchamia zapytanie i zwraca obietnicę (ang. *promise*), której kod (wywołujący owo zapytanie) powinien użyć do uzyskania wyniku. -Getting a response is usually a two-stage process. +Uzyskanie odpowiedzi jest zwykle procesem dwuetapowym. -**First, the `promise`, returned by `fetch`, resolves with an object of the built-in [Response](https://fetch.spec.whatwg.org/#response-class) class as soon as the server responds with headers.** +**Po pierwsze `obietnica`, zwrócona przez `fetch`, rozwiązuje się za pomocą obiektu wbudowanej klasy [Response](https://fetch.spec.whatwg.org/#response-class) , gdy tylko serwer odpowie nagłówkami.** -At this stage we can check HTTP status, to see whether it is successful or not, check headers, but don't have the body yet. +Na tym etapie możemy sprawdzić status HTTP, aby zobaczyć czy zapytanie się powiodło czy nie, możemy również sprawdzić nagłówki, ale jeszcze nie mamy dostępu do ciała odpowiedzi. -The promise rejects if the `fetch` was unable to make HTTP-request, e.g. network problems, or there's no such site. Abnormal HTTP-statuses, such as 404 or 500 do not cause an error. +Obietnica zostaje odrzucona jeżeli `fetch` nie był w stanie wykonać zapytania HTTP, np. ze względu problemy sieciowe lub brak strony, do której skierowano zapytanie. Nieprawidłowe statusy HTTP takie jak 404 lub 500 nie powodują błędu. -We can see HTTP-status in response properties: +Informację o statusie HTTP znajdziemy wśród właściwości odpowiedzi: -- **`status`** -- HTTP status code, e.g. 200. -- **`ok`** -- boolean, `true` if the HTTP status code is 200-299. +- **`status`** -- kod odpowiedzi HTTP, np. 200. +- **`ok`** -- typ logiczny, `true` jeżeli kod odpowiedzi HTTP jest z zakresu 200-299. -For example: +Przykładowo: ```js let response = await fetch(url); -if (response.ok) { // if HTTP-status is 200-299 - // get the response body (the method explained below) +if (response.ok) { // jeżeli kod odpowiedzi HTTP jest z zakresu 200-299 + // pobierz ciało odpowiedzi (wyjaśnienie metody poniżej) let json = await response.json(); } else { - alert("HTTP-Error: " + response.status); + alert("Błąd HTTP: " + response.status); } ``` -**Second, to get the response body, we need to use an additional method call.** +**Po drugie, aby pobrać ciało odpowiedzi należy wywołać kolejną metodę.** -`Response` provides multiple promise-based methods to access the body in various formats: +`Response` (pol. *odpowiedź*) zapewnia wiele metod, bazujących na obietnicach, które pozwalają na dostęp do ciała odpowiedzi i zwrócenie go w różnych formach: -- **`response.text()`** -- read the response and return as text, -- **`response.json()`** -- parse the response as JSON, -- **`response.formData()`** -- return the response as `FormData` object (explained in the [next chapter](info:formdata)), -- **`response.blob()`** -- return the response as [Blob](info:blob) (binary data with type), -- **`response.arrayBuffer()`** -- return the response as [ArrayBuffer](info:arraybuffer-binary-arrays) (low-level representaion of binary data), -- additionally, `response.body` is a [ReadableStream](https://streams.spec.whatwg.org/#rs-class) object, it allows to read the body chunk-by-chunk, we'll see an example later. +- **`response.text()`** -- odczytaj odpowiedź i zwróć jako tekst, +- **`response.json()`** -- odczytaj odpowiedź i zwróć jako JSON, +- **`response.formData()`** -- zwróć odpowiedź jako obiekt typu `FormData` (wyjaśnienie w [następnym rozdziale](info:formdata)), +- **`response.blob()`** -- zwróć odpowiedź jako [Blob](info:blob) (dane binarne z typem), +- **`response.arrayBuffer()`** -- zwróć odpowiedź jako [ArrayBuffer](info:arraybuffer-binary-arrays) (niskopoziomowa reprezentacja danych binarnych), +- ponadto `response.body` jest sam w sobie obiektem typu [ReadableStream](https://streams.spec.whatwg.org/#rs-class), co pozwala na odczytywanie go kawałek po kawałku, co zostanie pokazane w kolejnym przykładzie. -For instance, let's get a JSON-object with latest commits from GitHub: +Pobierzmy dla przykładu obiekt JSON z ostatnimi commitami z GitHuba. ```js run async let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'; @@ -81,7 +81,7 @@ let commits = await response.json(); // read response body and parse as JSON alert(commits[0].author.login); ``` -Or, the same without `await`, using pure promises syntax: +Bądź to samo, ale bez `await`, a jedynie za pomocą czystej składni obietnic: ```js run fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits') @@ -89,70 +89,70 @@ fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commi .then(commits => alert(commits[0].author.login)); ``` -To get the reponse text, `await response.text()` instead of `.json()`: +Aby pobrać odpowiedź jako tekst, użyj `await response.text()` zamiast `.json()`: ```js run async let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'); -let text = await response.text(); // read response body as text +let text = await response.text(); // odczytaj ciało odpowiedzi jako tekst alert(text.slice(0, 80) + '...'); ``` -As a show-case for reading in binary format, let's fetch and show a logo image of ["fetch" specification](https://fetch.spec.whatwg.org) (see chapter [Blob](info:blob) for details about operations on `Blob`): +Aby zaprezentować odczyt danych w formacie binarnym, pobierzmy obraz logo [specyfikacji "fetch"](https://fetch.spec.whatwg.org) (patrz rozdział [Blob](info:blob) odnośnie operacji na obiekcie typu `Blob`): ```js async run let response = await fetch('/article/fetch/logo-fetch.svg'); *!* -let blob = await response.blob(); // download as Blob object +let blob = await response.blob(); // pobierz logo jako obiekt typu Blob */!* -// create for it +// stwórz dla niego znacznik let img = document.createElement('img'); img.style = 'position:fixed;top:10px;left:10px;width:100px'; document.body.append(img); -// show it +// wyświetl je img.src = URL.createObjectURL(blob); -setTimeout(() => { // hide after three seconds +setTimeout(() => { // ukryj po upływie trzech sekund img.remove(); URL.revokeObjectURL(img.src); }, 3000); ``` ````warn -We can choose only one body-reading method. +Można wybrać tyko jedną z metod odczytywania ciała odpowiedzi. -If we've already got the response with `response.text()`, then `response.json()` won't work, as the body content has already been processed. +Jeśli już zdecydowaliśmy się na `response.text()`, wówczas `response.json()` nie zadziała, ponieważ zawartość ciała odpowiedzi została już wcześniej przetworzona. ```js -let text = await response.text(); // response body consumed -let parsed = await response.json(); // fails (already consumed) +let text = await response.text(); // ciało odpowiedzi zostaje przetworzone +let parsed = await response.json(); // nie powiedzie się (przetworzone wcześniej) ```` -## Response headers +## Nagłówki odpowiedzi -The response headers are available in a Map-like headers object in `response.headers`. +Nagłówki odpowiedzi są dostępne w obiekcie nagłówków podobnym do obiektu Map, a konkretnie w `response.headers`. -It's not exactly a Map, but it has similar methods to get individual headers by name or iterate over them: +Nie jest do dokładnie Map, aczkolwiek posiada podobne metody, służące do pobrania poszczególnych nagłówków za pomocą nazwy lub poprzez iterowanie po nich: ```js run async let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'); -// get one header +// pobieramy jeden nagłówek alert(response.headers.get('Content-Type')); // application/json; charset=utf-8 -// iterate over all headers +// iterujemy po wszystkich nagłówkach for (let [key, value] of response.headers) { alert(`${key} = ${value}`); } ``` -## Request headers +## Nagłówki żądania -To set a request header in `fetch`, we can use the `headers` option. It has an object with outgoing headers, like this: +Aby zdefiniować nagłówek w żądaniu `fetch`, użyjemy właściwości `headers`, która zawiera obiekt z wychodzącymi nagłówkami: ```js let response = fetch(protectedUrl, { @@ -162,7 +162,7 @@ let response = fetch(protectedUrl, { }); ``` -...But there's a list of [forbidden HTTP headers](https://fetch.spec.whatwg.org/#forbidden-header-name) that we can't set: +... Istnieją również [zabronione nagłówki HTTP](https://fetch.spec.whatwg.org/#forbidden-header-name), których nie możemy zdefiniować: - `Accept-Charset`, `Accept-Encoding` - `Access-Control-Request-Headers` @@ -185,27 +185,27 @@ let response = fetch(protectedUrl, { - `Proxy-*` - `Sec-*` -These headers ensure proper and safe HTTP, so they are controlled exclusively by the browser. +Dzięki nim protokół HTTP działa prawidłowo i jest bezpieczny, dlatego też są pod pełną kontrolą przeglądarki. -## POST requests +## Żądania POST -To make a `POST` request, or a request with another method, we need to use `fetch` options: +Ażeby wykonać żądanie typu `POST` lub jakiekolwiek inne żądanie sieciowe musimy użyć opcji dostępnych w metodzie `fetch`: -- **`method`** -- HTTP-method, e.g. `POST`, -- **`body`** -- the request body, one of: - - a string (e.g. JSON-encoded), - - `FormData` object, to submit the data as `form/multipart`, - - `Blob`/`BufferSource` to send binary data, - - [URLSearchParams](info:url), to submit the data in `x-www-form-urlencoded` encoding, rarely used. +- **`method`** -- metoda HTTP, np. `POST`, +- **`body`** -- ciało żądania, może przyjąć formę: + - łańcucha znaków (np. w formacie JSON), + - obiektu `FormData`, aby móc przesłać dane jako `form/multipart`, + - `Blob`/`BufferSource`, aby przesłać dane w formie binarnej, + - [URLSearchParams](info:url), aby przesłać dane jako `x-www-form-urlencoded`, rzadko używane. -The JSON format is used most of the time. +Najczęściej używanym formatem jest JSON. -For example, this code submits `user` object as JSON: +Przykładowo, ten kod przesyła obiekt `user` jako JSON: ```js run async let user = { - name: 'John', - surname: 'Smith' + name: 'Jan', + surname: 'Kowalski' }; *!* @@ -222,15 +222,15 @@ let result = await response.json(); alert(result.message); ``` -Please note, if the request `body` is a string, then `Content-Type` header is set to `text/plain;charset=UTF-8` by default. +Należy pamiętać, że jeżeli ciało żądania (`body`) jest łańcuchem znaków, wówczas nagłówek `Content-Type` domyślnie ustawiony jest jako `text/plain;charset=UTF-8`. -But, as we're going to send JSON, we use `headers` option to send `application/json` instead, the correct `Content-Type` for JSON-encoded data. +Ponieważ jednak zamierzamy wysłać obiekt JSON, użyjemy obiektu `headers` do ustawienia nagłówka `Content-Type` jako `application/json`, czyli właściwego dla danych zakodowanych w formacie JSON. -## Sending an image +## Wysyłanie obrazu -We can also submit binary data with `fetch` using `Blob` or `BufferSource` objects. +Możemy także za pomocą `fetch`przesłać dane binarne, używając obiektów `Blob` albo `BufferSource`. -In this example, there's a `` where we can draw by moving a mouse over it. A click on the "submit" button sends the image to server: +W poniższym przykładzie mamy znacznik ``, który pozwala na rysowanie poprzez poruszanie nad nim myszką. Kliknięcie na przycisk "Prześlij" wysyła obraz do serwera: ```html run autorun height="90" @@ -252,7 +252,7 @@ In this example, there's a `` where we can draw by moving a mouse over i body: blob }); - // the server responds with confirmation and the image size + // serwer potwierdza zapisanie obrazu oraz podaje jego rozmiar let result = await response.json(); alert(result.message); } @@ -261,9 +261,9 @@ In this example, there's a `` where we can draw by moving a mouse over i ``` -Please note, here we don't set `Content-Type` header manually, because a `Blob` object has a built-in type (here `image/png`, as generated by `toBlob`). For `Blob` objects that type becomes the value of `Content-Type`. +Zauważ, że nie ustawiamy ręcznie nagłówka `Content-Type`, ponieważ obiekt `Blob` posiada wbudowany typ (tutaj `image/png`, wymuszony przez metodę `toBlob`). Dla obiektów `Blob` ten typ zostaje ustawiony dla nagłówka `Content-Type`. -The `submit()` function can be rewritten without `async/await` like this: +Funkcję `submit()` można również przepisać nie używając składni `async/await` w taki sposób: ```js function submit() { @@ -278,13 +278,13 @@ function submit() { } ``` -## Summary +## Podsumowanie -A typical fetch request consists of two `await` calls: +Typowe żądanie `fetch` składa się z dwóch wywołań metody `await`: ```js -let response = await fetch(url, options); // resolves with response headers -let result = await response.json(); // read body as json +let response = await fetch(url, options); // rozwiązuje się z nagłówkami odpowiedzi +let result = await response.json(); // odczytuje ciało jako JSON ``` Or, without `await`: @@ -292,24 +292,24 @@ Or, without `await`: ```js fetch(url, options) .then(response => response.json()) - .then(result => /* process result */) + .then(result => /* zrób coś z parametrem result */) ``` -Response properties: -- `response.status` -- HTTP code of the response, -- `response.ok` -- `true` is the status is 200-299. -- `response.headers` -- Map-like object with HTTP headers. +Właściwości żądania: +- `response.status` -- kod odpowiedzi HTTP, +- `response.ok` -- `true` jeżeli kod odpowiedzi to 200-299. +- `response.headers` -- obiekt podobny do typu Map z nagłówkami HTTP. -Methods to get response body: -- **`response.text()`** -- return the response as text, -- **`response.json()`** -- parse the response as JSON object, -- **`response.formData()`** -- return the response as `FormData` object (form/multipart encoding, see the next chapter), -- **`response.blob()`** -- return the response as [Blob](info:blob) (binary data with type), -- **`response.arrayBuffer()`** -- return the response as [ArrayBuffer](info:arraybuffer-binary-arrays) (low-level binary data), +Metody służące do przetwarzania ciała odpowiedzi: +- **`response.text()`** -- zwróć odpowiedź jako tekst, +- **`response.json()`** -- odczytaj odpowiedź jako obiekt JSON, +- **`response.formData()`** -- zwróć odpowiedź jako obiekt `FormData` (kodowanie form/multipart, zobacz następny rozdział), +- **`response.blob()`** -- zwróć odpowiedź jako [Blob](info:blob) (dane binarne z typem), +- **`response.arrayBuffer()`** -- zwróć odpowiedź jako [ArrayBuffer](info:arraybuffer-binary-arrays) (niskopoziomowa reprezentacja danych binarnych), -Fetch options so far: -- `method` -- HTTP-method, -- `headers` -- an object with request headers (not any header is allowed), -- `body` -- the data to send (request body) as `string`, `FormData`, `BufferSource`, `Blob` or `UrlSearchParams` object. +Poznane jak dotąd opcje metody `fetch`: +- `method` -- metoda żądania HTTP, +- `headers` -- obiekt z nagłówkami żądania (nie każdy dowolny nagłówek jest dozwolony), +- `body` -- dane do wysyłki (ciało żądania) jako `string`, `FormData`, `BufferSource`, `Blob` lub obiekt `UrlSearchParams`. -In the next chapters we'll see more options and use cases of `fetch`. +W następnych rozdziałach poznamy więcej opcji i przypadków użycia metody `fetch`. From 625b23f1878c05617b4d7550e4ad2bc312206df2 Mon Sep 17 00:00:00 2001 From: mitroc Date: Sat, 5 Oct 2019 23:24:03 +0200 Subject: [PATCH 07/12] Correct 'article.md' --- 5-network/01-fetch/article.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/5-network/01-fetch/article.md b/5-network/01-fetch/article.md index 6983abfb5..82cb7f80a 100644 --- a/5-network/01-fetch/article.md +++ b/5-network/01-fetch/article.md @@ -3,7 +3,7 @@ Ilekroć jest to potrzebne, JavaScript potrafi wykonywać żądania sieciowe do serwera i pobierać nowe informacje. -Można na przykład użyć zapytania sieciowego do: +Można na przykład użyć żądania sieciowego do: - złożenia zamówienia, - wyświetlenia informacji o użytkowniku, @@ -75,7 +75,7 @@ let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/c let response = await fetch(url); *!* -let commits = await response.json(); // read response body and parse as JSON +let commits = await response.json(); // odczytaj ciało odpowiedzi i zwróć jako JSON */!* alert(commits[0].author.login); @@ -236,7 +236,7 @@ W poniższym przykładzie mamy znacznik ``, który pozwala na rysowanie - + ``` -In this example, the server code is not presented, as it's beyound our scope. The server accepts the POST request and replies "User saved". +Kod serwera jest poza naszym zakresem zainteresowania, nie pokazujemy go zatem w tym przykładzie. W każdym razie serwer akceptuje żądanie POST i odpowiada "Zapisano użytkownika". -## FormData Methods +## Metody FormData -We can modify fields in `FormData` with methods: +Pola w `FormData` możemy zmieniać następującymi metodami: -- `formData.append(name, value)` - add a form field with the given `name` and `value`, -- `formData.append(name, blob, fileName)` - add a field as if it were ``, the third argument `fileName` sets file name (not form field name), as it it were a name of the file in user's filesystem, -- `formData.delete(name)` - remove the field with the given `name`, -- `formData.get(name)` - get the value of the field with the given `name`, -- `formData.has(name)` - if there exists a field with the given `name`, returns `true`, otherwise `false` +- `formData.append(name, value)` - dodaj pole formularza z podanymi `name` oraz `value`, +- `formData.append(name, blob, fileName)` - dodaj pole tak jakby było znacznikiem ``, trzeci argument `fileName` ustawia nazwę pliku (nie nazwę formularza), tak jakby była nazwą pliku w systemie plików użytkownika, +- `formData.delete(name)` - usuń pole `name`, +- `formData.get(name)` - pobierz wartość pola `name`, +- `formData.has(name)` - jeżeli istniej pole `name`, zwróć `true`, w innym przypadku zwróć `false` -A form is technically allowed to have many fields with the same `name`, so multiple calls to `append` add more same-named fields. +Formularz, technicznie rzecz ujmując, może mieć wiele pól `name`, tak więc wiele wywołań metody `append` dodaje więcej pól o tej samej nazwie. -There's also method `set`, with the same syntax as `append`. The difference is that `.set` removes all fields with the given `name`, and then appends a new field. So it makes sure there's only field with such `name`, the rest is just like `append`: +Istnieje również metoda `set`, która ma taką samą składnię jak `append`. Różnica polega na tym, że `.set` usuwa wszystkie pola `name`, a następnie dodaje nowe pole. Dzięki temu upewnia się, że istnieje tylko jedno pole z podanym `name`. Pozostała część wygląda jak w metodzie `append`: - `formData.set(name, value)`, - `formData.set(name, blob, fileName)`. -Also we can iterate over formData fields using `for..of` loop: +Możemy również iterować po polach `formData` używając pętli `for..of`: ```js run let formData = new FormData(); formData.append('key1', 'value1'); formData.append('key2', 'value2'); -// List key/value pairs +// Wylicz pary klucz/wartość for(let [name, value] of formData) { - alert(`${name} = ${value}`); // key1=value1, then key2=value2 + alert(`${name} = ${value}`); // key1=value1 oraz key2=value2 } ``` -## Sending a form with a file +## Wysyłanie formularza z plikiem -The form is always sent as `Content-Type: form/multipart`, this encoding allows to send files. So, `` fields are sent also, similar to a usual form submission. +Formularz jest zawsze wysyłany jako `Content-Type: form/multipart`, gdyż takie kodowanie pozwala na wysyłkę plików. Tak więc pola `` są również wysyłane, podobnie jak to ma miejsce w zwykłym przesłaniu formularza. -Here's an example with such form: +Oto przykład takiego formularza: ```html run autorun
- + Picture:
@@ -110,21 +110,21 @@ Here's an example with such form: ``` -## Sending a form with Blob data +## Wysyłanie formularza z danymi typu Blob -As we've seen in the chapter , it's easy to send dynamically generated binary data e.g. an image, as `Blob`. We can supply it directly as `fetch` parameter `body`. +W rozdziale widzieliśmy, że wysyłka dynamicznie generowanych danych binarnych, np. obrazu jako `Blob`, jest dość prosta. Możemy go umieścić jako parametr `body` w metodzie `fetch`. -In practice though, it's often convenient to send an image not separately, but as a part of the form, with additional fields, such as "name" and other metadata. +W praktyce jednak często wygodniej jest wysłać obraz nie osobno, ale jako część formularza, z dodatkowymi polami, takimi jak "nazwa” i inne metadane. -Also, servers are usually more suited to accept multipart-encoded forms, rather than raw binary data. +Ponadto serwery są zwykle bardziej przystosowane do akceptowania formularzy zakodowanych w postaci wieloczęściowej niż surowych danych binarnych. -This example submits an image from ``, along with some other fields, as a form, using `FormData`: +W tym przykładzie pobieramy jako formularz obraz ze znacznika ``, wraz z innymi polami, używając `FormData`: ```html run autorun height="90" - + ``` -Kod serwera jest poza naszym zakresem zainteresowania, nie pokazujemy go zatem w tym przykładzie. W każdym razie serwer akceptuje żądanie POST i odpowiada "Zapisano użytkownika". +Kod serwera jest poza naszym zakresem zainteresowania, nie pokazujemy go zatem w tym przykładzie. W każdym razie serwer akceptuje żądanie POST i odpowiada "Użytkownik zapisany". ## Metody FormData From c178a4158790c4d20f82b3d7c300233a8e66267b Mon Sep 17 00:00:00 2001 From: mitroc Date: Sun, 6 Oct 2019 01:30:35 +0200 Subject: [PATCH 10/12] Translate 'server.js' --- 5-network/02-formdata/post.view/server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/5-network/02-formdata/post.view/server.js b/5-network/02-formdata/post.view/server.js index a335b07b1..5b0483118 100644 --- a/5-network/02-formdata/post.view/server.js +++ b/5-network/02-formdata/post.view/server.js @@ -9,7 +9,7 @@ let router = new Router(); router.post('/user', async (ctx) => { ctx.body = { - message: "User saved" + message: "Użytkownik zapisany" }; }); @@ -34,7 +34,7 @@ router.post('/image-form', async (ctx) => { }); ctx.body = { - message: `Image saved, firstName: ${fields.firstName}, Image size:${files[0].length}, fileName: ${files[0].filename}` + message: `Obraz zapisany, imię: ${fields.firstName}, rozmiar obrazu:${files[0].length}, nazwa pliku: ${files[0].filename}.` }; }); @@ -61,7 +61,7 @@ router.post('/user-avatar', async (ctx) => { }); ctx.body = { - message: `User with picture, firstName: ${fields.firstName}, picture size:${files[0].length}` + message: `Użytkownik ze zdjęciem, imię: ${fields.firstName}, rozmiar obrazu:${files[0].length}.` }; }); From 3b71594a9b5bd703a9b751941f28a1f08fc1e2c8 Mon Sep 17 00:00:00 2001 From: mitroc Date: Tue, 8 Oct 2019 11:35:36 +0200 Subject: [PATCH 11/12] Apply suggestions from code review Co-Authored-By: Jakub Drozdek <30927218+jakubdrozdek@users.noreply.github.com> --- .../01-fetch/01-fetch-users/_js.view/test.js | 2 +- 5-network/01-fetch/01-fetch-users/solution.md | 4 +- 5-network/01-fetch/01-fetch-users/task.md | 8 ++-- 5-network/01-fetch/article.md | 38 +++++++++--------- 5-network/02-formdata/article.md | 40 +++++++++---------- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/5-network/01-fetch/01-fetch-users/_js.view/test.js b/5-network/01-fetch/01-fetch-users/_js.view/test.js index ed8d03137..f32a5d4b3 100644 --- a/5-network/01-fetch/01-fetch-users/_js.view/test.js +++ b/5-network/01-fetch/01-fetch-users/_js.view/test.js @@ -1,7 +1,7 @@ describe("getUsers", function() { it("pobiera użytkowników GitHuba", async function() { - let users = await getUsers(['iliakan', 'remy', 'brak.użytkowników']); + let users = await getUsers(['iliakan', 'remy', 'nieistniejący.użytkownik']); assert.equal(users[0].login, 'iliakan'); assert.equal(users[1].login, 'remy'); assert.equal(users[2], null); diff --git a/5-network/01-fetch/01-fetch-users/solution.md b/5-network/01-fetch/01-fetch-users/solution.md index 8afaa86cd..369e34fbe 100644 --- a/5-network/01-fetch/01-fetch-users/solution.md +++ b/5-network/01-fetch/01-fetch-users/solution.md @@ -1,5 +1,5 @@ -Aby pobrać użytkownika wykorzystamy: `fetch('https://api.github.com/users/USERNAME')`. +Do pobrania użytkownika wykorzystamy: `fetch('https://api.github.com/users/USERNAME')`. Jeżeli odpowiedź zostanie zwrócona ze statusem `200`, wywołamy metodę `.json()`, aby móc odczytać javascriptowy obiekt. @@ -37,4 +37,4 @@ Zauważ, że metoda `.then` jest dołączona bezpośrednio do `fetch`, więc nie Gdybyśmy jednak użyli `await Promise.all(names.map(name => fetch(...)))` i wywołali metodę `.json()` dopiero na rezultacie, wówczas musiałaby ona czekać, aż wszystkie żądania zwrócą swoje odpowiedzi. Dołączając `.json()` bezpośrednio do każdego zapytania `fetch` możemy być pewni, że pojedyncze zapytania zaczną odczytywać dane jako JSON, bez czekania nawzajem na siebie. -Jest to przykład tego, jak przydatne może być niskopoziomowe Promise API, nawet jeżeli głównie korzystamy z `async/await`. \ No newline at end of file +Jest to przykład tego, jak przydatne może być niskopoziomowe Promise API, nawet jeżeli głównie korzystamy z `async/await`. diff --git a/5-network/01-fetch/01-fetch-users/task.md b/5-network/01-fetch/01-fetch-users/task.md index b4ea5f2d4..862ef551e 100644 --- a/5-network/01-fetch/01-fetch-users/task.md +++ b/5-network/01-fetch/01-fetch-users/task.md @@ -1,13 +1,13 @@ # Pobierz użytkowników z GitHuba -Stwórz asynchroniczną funkcję `getUsers(names)`, która pobiera z GitHuba tablicę z nazwami użytkowników, a następnie zwraca tablicę z odpowiadającymi im użytkownikami. +Stwórz asynchroniczną funkcję `getUsers(names)`, która otrzymuje tablicę z loginami do GitHuba, a następnie zwraca tablicę z odpowiadającymi im użytkownikami. -Informacje o użytkowniku przypisanym do `USERNAME`, znajdują się pod adresem url: `https://api.github.com/users/USERNAME`. +Informacje o użytkowniku przypisanym do `USERNAME`, znajdują się pod adresem: `https://api.github.com/users/USERNAME`. -W środowisku izolowanym znajduje się przykład testowy. +W naszym środowisku izolowanym znajduje się przykład testowy. Ważne informacje: 1. Można wykonać tylko jedno żądanie `fetch` o dane użytkownika. 2. Żądania nie powinny na siebie oczekiwać. Chodzi o to, aby dane dotarły jak najszybciej. -3. Jeżeli żądanie się nie powiedzie lub nie będzie użytkownika o podanej nazwie, funkcja powinna zwrócić `null` w tablicy wynikowej. \ No newline at end of file +3. Jeżeli żądanie się nie powiedzie lub nie będzie użytkownika o podanej nazwie, funkcja powinna zwrócić `null` w tablicy wynikowej. diff --git a/5-network/01-fetch/article.md b/5-network/01-fetch/article.md index 82cb7f80a..f564d6a40 100644 --- a/5-network/01-fetch/article.md +++ b/5-network/01-fetch/article.md @@ -12,11 +12,11 @@ Można na przykład użyć żądania sieciowego do: ...I to wszystko bez przeładowania strony! -Istnieje nadrzędny termin "AJAX" (skrót od Asynchronous JavaScript And XML) dotyczący żądań sieciowych w JavaScript. Nie musimy jednak używać XML-a: skrót ten pochodzi z dawnych czasów, stąd też zawiera takie właśnie słowo. Być może znasz już ten termin. +Istnieje nadrzędny termin "AJAX" (skrót od Asynchronous JavaScript And XML) dotyczący żądań sieciowych w JavaScripcie. Nie musimy jednak używać XML-a: skrót ten pochodzi z dawnych czasów, stąd też zawiera takie właśnie słowo. Być może znasz już ten termin. Istnieje wiele sposobów wysłania żądania sieciowego i pobrania informacji z serwera. -Metoda `fetch()` jest nowoczesna i wszechstronna, zaczniemy więc od niej. Nie jest ona wspierana przez stare przeglądarki (można ją zaimplementować skryptem typu polyfill), jest natomiast bardzo dobrze obsługiwana przez współczesne przeglądarki. +Metoda `fetch()` jest nowoczesna i wszechstronna, dlatego od niej zaczniemy. Nie jest ona wspierana przez stare przeglądarki (można ją dodać poprzez odpowiednią łatkę - ang. *polyfill*), jest natomiast bardzo dobrze obsługiwana przez współczesne przeglądarki. Podstawowa składnia jest następująca: @@ -29,15 +29,15 @@ let promise = fetch(url, [options]) Bez `options` mamy do czynienia ze zwykłym zapytaniem GET, pobierającym zawartość adresu `url`. -Przeglądarka natychmiast uruchamia zapytanie i zwraca obietnicę (ang. *promise*), której kod (wywołujący owo zapytanie) powinien użyć do uzyskania wyniku. +Przeglądarka natychmiast uruchamia zapytanie i zwraca obietnicę (ang. *promise*), której kod wywołujący powinien użyć do uzyskania wyniku. Uzyskanie odpowiedzi jest zwykle procesem dwuetapowym. -**Po pierwsze `obietnica`, zwrócona przez `fetch`, rozwiązuje się za pomocą obiektu wbudowanej klasy [Response](https://fetch.spec.whatwg.org/#response-class) , gdy tylko serwer odpowie nagłówkami.** +**Po pierwsze, obietnica `promise` zwrócona przez `fetch`, rozwiązuje się (ang. *resolves*) do obiektu wbudowanej klasy [Response](https://fetch.spec.whatwg.org/#response-class) , gdy tylko serwer odpowie nagłówkami.** -Na tym etapie możemy sprawdzić status HTTP, aby zobaczyć czy zapytanie się powiodło czy nie, możemy również sprawdzić nagłówki, ale jeszcze nie mamy dostępu do ciała odpowiedzi. +Na tym etapie możemy sprawdzić status żądania HTTP, aby dowiedzieć się, czy się ono powiodło, albo przejrzeć nagłówki. Nie mamy jednak jeszcze dostępu do ciała odpowiedzi. -Obietnica zostaje odrzucona jeżeli `fetch` nie był w stanie wykonać zapytania HTTP, np. ze względu problemy sieciowe lub brak strony, do której skierowano zapytanie. Nieprawidłowe statusy HTTP takie jak 404 lub 500 nie powodują błędu. +Obietnica jest odrzucana (ang. *rejects*), jeżeli `fetch` jest w stanie wykonać zapytania HTTP, np. ze względu na problemy sieciowe lub brak strony, do której skierowano zapytanie. Nieprawidłowe statusy HTTP, takie jak 404 lub 500, nie powodują błędu. Informację o statusie HTTP znajdziemy wśród właściwości odpowiedzi: @@ -50,23 +50,23 @@ Przykładowo: let response = await fetch(url); if (response.ok) { // jeżeli kod odpowiedzi HTTP jest z zakresu 200-299 - // pobierz ciało odpowiedzi (wyjaśnienie metody poniżej) + // pobierz ciało odpowiedzi (wyjaśnione poniżej) let json = await response.json(); } else { alert("Błąd HTTP: " + response.status); } ``` -**Po drugie, aby pobrać ciało odpowiedzi należy wywołać kolejną metodę.** +**Po drugie, aby pobrać ciało odpowiedzi, należy wywołać kolejną metodę.** -`Response` (pol. *odpowiedź*) zapewnia wiele metod, bazujących na obietnicach, które pozwalają na dostęp do ciała odpowiedzi i zwrócenie go w różnych formach: +Obiekt klasy `Response` (pol. *odpowiedź*) zapewnia wiele metod bazujących na obietnicach, które pozwalają na dostęp do ciała odpowiedzi i zwrócenie go w różnych formach: - **`response.text()`** -- odczytaj odpowiedź i zwróć jako tekst, - **`response.json()`** -- odczytaj odpowiedź i zwróć jako JSON, - **`response.formData()`** -- zwróć odpowiedź jako obiekt typu `FormData` (wyjaśnienie w [następnym rozdziale](info:formdata)), - **`response.blob()`** -- zwróć odpowiedź jako [Blob](info:blob) (dane binarne z typem), - **`response.arrayBuffer()`** -- zwróć odpowiedź jako [ArrayBuffer](info:arraybuffer-binary-arrays) (niskopoziomowa reprezentacja danych binarnych), -- ponadto `response.body` jest sam w sobie obiektem typu [ReadableStream](https://streams.spec.whatwg.org/#rs-class), co pozwala na odczytywanie go kawałek po kawałku, co zostanie pokazane w kolejnym przykładzie. +- ponadto `response.body` jest sam w sobie obiektem typu [ReadableStream](https://streams.spec.whatwg.org/#rs-class), co pozwala na odczytywanie go kawałek po kawałku. Ale o tym nieco później. Pobierzmy dla przykładu obiekt JSON z ostatnimi commitami z GitHuba. @@ -162,7 +162,7 @@ let response = fetch(protectedUrl, { }); ``` -... Istnieją również [zabronione nagłówki HTTP](https://fetch.spec.whatwg.org/#forbidden-header-name), których nie możemy zdefiniować: +... Istnieją również [zabronione nagłówki HTTP](https://fetch.spec.whatwg.org/#forbidden-header-name), których nie możemy ustawić: - `Accept-Charset`, `Accept-Encoding` - `Access-Control-Request-Headers` @@ -189,7 +189,7 @@ Dzięki nim protokół HTTP działa prawidłowo i jest bezpieczny, dlatego też ## Żądania POST -Ażeby wykonać żądanie typu `POST` lub jakiekolwiek inne żądanie sieciowe musimy użyć opcji dostępnych w metodzie `fetch`: +Do wykonania żądania z metodą `POST` lub jakąkolwiek inną musimy użyć opcji dostępnych w funkcji `fetch`: - **`method`** -- metoda HTTP, np. `POST`, - **`body`** -- ciało żądania, może przyjąć formę: @@ -222,13 +222,13 @@ let result = await response.json(); alert(result.message); ``` -Należy pamiętać, że jeżeli ciało żądania (`body`) jest łańcuchem znaków, wówczas nagłówek `Content-Type` domyślnie ustawiony jest jako `text/plain;charset=UTF-8`. +Należy pamiętać, że jeżeli ciało żądania (`body`) jest łańcuchem znaków, wówczas nagłówek `Content-Type` domyślnie ustawiony jest na `text/plain;charset=UTF-8`. -Ponieważ jednak zamierzamy wysłać obiekt JSON, użyjemy obiektu `headers` do ustawienia nagłówka `Content-Type` jako `application/json`, czyli właściwego dla danych zakodowanych w formacie JSON. +Ponieważ jednak zamierzamy wysłać obiekt JSON, użyjemy obiektu `headers` do ustawienia nagłówka `Content-Type` na `application/json`, czyli właściwego dla danych zakodowanych w formacie JSON. ## Wysyłanie obrazu -Możemy także za pomocą `fetch`przesłać dane binarne, używając obiektów `Blob` albo `BufferSource`. +Za pomocą `fetch` możemy także przesłać dane binarne, używając obiektów `Blob` albo `BufferSource`. W poniższym przykładzie mamy znacznik ``, który pozwala na rysowanie poprzez poruszanie nad nim myszką. Kliknięcie na przycisk "Prześlij" wysyła obraz do serwera: @@ -263,7 +263,7 @@ W poniższym przykładzie mamy znacznik ``, który pozwala na rysowanie Zauważ, że nie ustawiamy ręcznie nagłówka `Content-Type`, ponieważ obiekt `Blob` posiada wbudowany typ (tutaj `image/png`, wymuszony przez metodę `toBlob`). Dla obiektów `Blob` ten typ zostaje ustawiony dla nagłówka `Content-Type`. -Funkcję `submit()` można również przepisać nie używając składni `async/await` w taki sposób: +Funkcję `submit()` można również przepisać z pominięciem składni `async/await` w taki sposób: ```js function submit() { @@ -280,10 +280,10 @@ function submit() { ## Podsumowanie -Typowe żądanie sieciowe składa się z dwóch wywołań metody `await`: +Typowe żądanie sieciowe składa się z dwóch wywołań `await`: ```js -let response = await fetch(url, options); // rozwiązuje się z nagłówkami odpowiedzi +let response = await fetch(url, options); // rozwiązuje się do obiektu z nagłówkami odpowiedzi let result = await response.json(); // odczytuje ciało jako JSON ``` @@ -297,7 +297,7 @@ fetch(url, options) Właściwości żądania: - `response.status` -- kod odpowiedzi HTTP, -- `response.ok` -- `true` jeżeli kod odpowiedzi to 200-299. +- `response.ok` -- `true` dla kodów odpowiedzi z przedziału 200-299. - `response.headers` -- obiekt podobny do typu Map z nagłówkami HTTP. Metody służące do przetwarzania ciała odpowiedzi: diff --git a/5-network/02-formdata/article.md b/5-network/02-formdata/article.md index 1e054a56a..1e698e18c 100644 --- a/5-network/02-formdata/article.md +++ b/5-network/02-formdata/article.md @@ -3,7 +3,7 @@ W niniejszym rozdziale omówimy wysyłkę formularzy HTML: z plikami lub bez, z dodatkowymi polami i tak dalej. -Pomoże nam w tym obiekt typu [FormData](https://xhr.spec.whatwg.org/#interface-formdata). Jak zapewne się domyślasz jest to obiekt reprezentujący dane formularza HTML. +Pomoże nam w tym obiekt typu [FormData](https://xhr.spec.whatwg.org/#interface-formdata). Jak zapewne się domyślasz, jest to obiekt reprezentujący dane formularza HTML. Konstruktor wygląda następująco: ```js @@ -14,7 +14,7 @@ Przechwyci on automatycznie wszystkie pola formularza HTML na stronie. `FormData` posiada tę szczególną cechę, że metody sieciowe takie jak `fetch` mogą przyjmować obiekt `FormData` jako ciało. Jest on wówczas kodowany i wysyłany jako `Content-Type: form/multipart`. -Od strony serwera wygląda to jak zwykłe przesłanie formularza. +Z perspektywy serwera wygląda to jak zwykłe przesłanie formularza. ## Wysyłanie prostego formularza @@ -47,26 +47,26 @@ Jak widać, to niemal jedna linijka: ``` -Kod serwera jest poza naszym zakresem zainteresowania, nie pokazujemy go zatem w tym przykładzie. W każdym razie serwer akceptuje żądanie POST i odpowiada "Użytkownik zapisany". +Kod serwera jest poza naszym zakresem zainteresowania, zatem nie pokazujemy go w tym przykładzie. W każdym razie serwer akceptuje żądanie POST i odpowiada komunikatem: "Użytkownik zapisany". ## Metody FormData Pola w `FormData` możemy zmieniać następującymi metodami: -- `formData.append(name, value)` - dodaj pole formularza z podanymi `name` oraz `value`, -- `formData.append(name, blob, fileName)` - dodaj pole tak jakby było znacznikiem ``, trzeci argument `fileName` ustawia nazwę pliku (nie nazwę formularza), tak jakby była nazwą pliku w systemie plików użytkownika, +- `formData.append(name, value)` - dodaj pole formularza o nazwie `name` i wartości `value`, +- `formData.append(name, blob, fileName)` - dodaj pole tak jakby było znacznikiem ``; trzeci argument `fileName` ustawia nazwę pliku (nie nazwę formularza), tak jakby była nazwą pliku w systemie plików użytkownika, - `formData.delete(name)` - usuń pole `name`, - `formData.get(name)` - pobierz wartość pola `name`, -- `formData.has(name)` - jeżeli istniej pole `name`, zwróć `true`, w innym przypadku zwróć `false` +- `formData.has(name)` - jeżeli istnieje pole `name`, zwróć `true`; w innym przypadku zwróć `false` -Formularz, technicznie rzecz ujmując, może mieć wiele pól `name`, tak więc wiele wywołań metody `append` dodaje więcej pól o tej samej nazwie. +Formularz, z technicznego punktu widzenia, może mieć pól o nazwie `name`, tak więc wiele wywołań metody `append` doda wiele pól o tej samej nazwie. -Istnieje również metoda `set`, która ma taką samą składnię jak `append`. Różnica polega na tym, że `.set` usuwa wszystkie pola `name`, a następnie dodaje nowe pole. Dzięki temu upewnia się, że istnieje tylko jedno pole z podanym `name`. Pozostała część wygląda jak w metodzie `append`: +Istnieje również metoda `set`, która ma taką samą składnię jak `append`. Różnica polega na tym, że `.set` usuwa wszystkie pola o nazwie `name`, a następnie dodaje nowe pole. Dzięki temu zapewnia, że istnieje tylko jedno pole o nazwie `name`. Pozostała część wygląda jak w metodzie `append`: - `formData.set(name, value)`, - `formData.set(name, blob, fileName)`. -Możemy również iterować po polach `formData` używając pętli `for..of`: +Możemy również iterować po polach `formData`, używając pętli `for..of`: ```js run let formData = new FormData(); @@ -75,20 +75,20 @@ formData.append('key2', 'value2'); // Wylicz pary klucz/wartość for(let [name, value] of formData) { - alert(`${name} = ${value}`); // key1=value1 oraz key2=value2 + alert(`${name}=${value}`); // key1=value1 oraz key2=value2 } ``` ## Wysyłanie formularza z plikiem -Formularz jest zawsze wysyłany jako `Content-Type: form/multipart`, gdyż takie kodowanie pozwala na wysyłkę plików. Tak więc pola `` są również wysyłane, podobnie jak to ma miejsce w zwykłym przesłaniu formularza. +Formularz jest zawsze wysyłany jako `Content-Type: form/multipart`, gdyż takie kodowanie pozwala na wysyłkę plików. Tak więc pola `` są również wysyłane, podobnie jak ma to miejsce w zwykłym przesłaniu formularza. Oto przykład takiego formularza: ```html run autorun
- Picture: + Obraz:
@@ -112,13 +112,13 @@ Oto przykład takiego formularza: ## Wysyłanie formularza z danymi typu Blob -W rozdziale widzieliśmy, że wysyłka dynamicznie generowanych danych binarnych, np. obrazu jako `Blob`, jest dość prosta. Możemy go umieścić jako parametr `body` w metodzie `fetch`. +W rozdziale pt. "" widzieliśmy, że wysyłka dynamicznie generowanych danych binarnych, np. obrazu jako `Blob`, jest dość prosta. Możemy go umieścić jako parametr `body` funkcji `fetch`. W praktyce jednak często wygodniej jest wysłać obraz nie osobno, ale jako część formularza, z dodatkowymi polami, takimi jak "nazwa” i inne metadane. -Ponadto serwery są zwykle bardziej przystosowane do akceptowania formularzy zakodowanych w postaci wieloczęściowej niż surowych danych binarnych. +Ponadto serwery są zwykle lepiej przystosowane do akceptowania formularzy zakodowanych w postaci wieloczęściowej (ang. *multipart*) niż surowych danych binarnych. -W tym przykładzie pobieramy jako formularz obraz ze znacznika ``, wraz z innymi polami, używając `FormData`: +W tym przykładzie wysyłamy w formularzu obraz ze znacznika `` wraz z innymi polami, używając do tego `FormData`: ```html run autorun height="90" @@ -166,9 +166,9 @@ Serwer odczytuje dane formularza i plik, tak jakby było to zwykłe przesyłanie ## Podsumowanie -Obiekty typu [FormData](https://xhr.spec.whatwg.org/#interface-formdata) służą do przechwytywania formularza HTML i przesłania go za pomocą metody `fetch` lub innej metody sieciowej. +Obiekty klasy [FormData](https://xhr.spec.whatwg.org/#interface-formdata) służą do przechwycenia formularza HTML i przesłania go za pomocą `fetch` lub innej funkcji sieciowej. -Możemy albo utworzyć `new FormData(form)` z formularza HTML form, abo stworzyć obiekt bez formularza, a następnie dołączyć do niego pola metodami: +Możemy albo utworzyć `new FormData(form)` na podstawie formularza HTML, albo stworzyć obiekt bez formularza, a następnie dołączyć do niego pola metodami: - `formData.append(name, value)` - `formData.append(name, blob, fileName)` @@ -177,8 +177,8 @@ Możemy albo utworzyć `new FormData(form)` z formularza HTML form, abo stworzy Zwróćmy uwagę na dwie osobliwości: -1. Metoda `set` usuwa pole o tej samej nazwie, a `append` nie. To jedynia różnica między nimi. -2. Aby wysłać plik, potrzebna jest 3-argumentowa składnia, gdzie ostatnim argumentem jest nazwa pliku, która zwykle pobierana jest z systemu plików na potrzeby ``. +1. Metoda `set` usuwa zduplikowane pola o tej samej nazwie, a `append` nie. To jedynia różnica między nimi. +2. Aby wysłać plik, potrzebna jest trójargumentowa składnia, gdzie ostatnim argumentem jest nazwa pliku, zwykle pobierana z systemu plików na potrzeby ``. Inne metody to: @@ -186,4 +186,4 @@ Inne metody to: - `formData.get(name)` - `formData.has(name)` -I tak to wygląda! +I to by było na tyle! From c20bed7e158f31b607c19ab0ecca4c0f8fe88fed Mon Sep 17 00:00:00 2001 From: mitroc Date: Sun, 20 Oct 2019 15:03:49 +0200 Subject: [PATCH 12/12] Apply code review suggestions --- 5-network/01-fetch/article.md | 10 +++++----- 5-network/02-formdata/article.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/5-network/01-fetch/article.md b/5-network/01-fetch/article.md index f564d6a40..32eb82358 100644 --- a/5-network/01-fetch/article.md +++ b/5-network/01-fetch/article.md @@ -99,13 +99,13 @@ let text = await response.text(); // odczytaj ciało odpowiedzi jako tekst alert(text.slice(0, 80) + '...'); ``` -Aby zaprezentować odczyt danych w formacie binarnym, pobierzmy obraz logo [specyfikacji "fetch"](https://fetch.spec.whatwg.org) (patrz rozdział [Blob](info:blob) odnośnie operacji na obiekcie typu `Blob`): +Aby zaprezentować odczyt danych w formacie binarnym, pobierzmy obraz logo [specyfikacji "fetch"](https://fetch.spec.whatwg.org) (patrz rozdział [Blob](info:blob) odnośnie operacji na obiekcie `Blob`): ```js async run let response = await fetch('/article/fetch/logo-fetch.svg'); *!* -let blob = await response.blob(); // pobierz logo jako obiekt typu Blob +let blob = await response.blob(); // pobierz logo jako obiekt Blob */!* // stwórz dla niego znacznik @@ -261,7 +261,7 @@ W poniższym przykładzie mamy znacznik ``, który pozwala na rysowanie ``` -Zauważ, że nie ustawiamy ręcznie nagłówka `Content-Type`, ponieważ obiekt `Blob` posiada wbudowany typ (tutaj `image/png`, wymuszony przez metodę `toBlob`). Dla obiektów `Blob` ten typ zostaje ustawiony dla nagłówka `Content-Type`. +Zauważ, że nie ustawiamy ręcznie nagłówka `Content-Type`, ponieważ obiekt `Blob` posiada wbudowany typ (tutaj `image/png`, wymuszony przez metodę `toBlob`). Dla obiektów `Blob` ten typ jest przekazywany do nagłówka `Content-Type`. Funkcję `submit()` można również przepisać z pominięciem składni `async/await` w taki sposób: @@ -298,7 +298,7 @@ fetch(url, options) Właściwości żądania: - `response.status` -- kod odpowiedzi HTTP, - `response.ok` -- `true` dla kodów odpowiedzi z przedziału 200-299. -- `response.headers` -- obiekt podobny do typu Map z nagłówkami HTTP. +- `response.headers` -- z nagłówkami HTTP, podobny do Map. Metody służące do przetwarzania ciała odpowiedzi: - **`response.text()`** -- zwróć odpowiedź jako tekst, @@ -310,6 +310,6 @@ Metody służące do przetwarzania ciała odpowiedzi: Poznane jak dotąd opcje metody `fetch`: - `method` -- metoda żądania HTTP, - `headers` -- obiekt z nagłówkami żądania (nie każdy dowolny nagłówek jest dozwolony), -- `body` -- dane do wysyłki (ciało żądania) jako `string`, `FormData`, `BufferSource`, `Blob` lub obiekt `UrlSearchParams`. +- `body` -- dane do wysyłki (ciało żądania) jako `string` albo obiekt `FormData`, `BufferSource`, `Blob` lub `UrlSearchParams`. W następnych rozdziałach poznamy więcej opcji i przypadków użycia metody `fetch`. diff --git a/5-network/02-formdata/article.md b/5-network/02-formdata/article.md index 1e698e18c..41971479f 100644 --- a/5-network/02-formdata/article.md +++ b/5-network/02-formdata/article.md @@ -3,7 +3,7 @@ W niniejszym rozdziale omówimy wysyłkę formularzy HTML: z plikami lub bez, z dodatkowymi polami i tak dalej. -Pomoże nam w tym obiekt typu [FormData](https://xhr.spec.whatwg.org/#interface-formdata). Jak zapewne się domyślasz, jest to obiekt reprezentujący dane formularza HTML. +Pomoże nam w tym obiekt [FormData](https://xhr.spec.whatwg.org/#interface-formdata). Jak zapewne się domyślasz, jest to obiekt reprezentujący dane formularza HTML. Konstruktor wygląda następująco: ```js