# Projekt rozszerzenia przeglądarki, część 2: Wywołanie API, użycie Local Storage
## Quiz przed lekcją
[Quiz przed lekcją](https://ff-quizzes.netlify.app/web/quiz/25)
### Wprowadzenie
W tej lekcji wywołasz API, przesyłając formularz rozszerzenia przeglądarki i wyświetlając wyniki w rozszerzeniu. Dodatkowo dowiesz się, jak przechowywać dane w lokalnej pamięci przeglądarki, aby móc je wykorzystać w przyszłości.
✅ Postępuj zgodnie z numerowanymi segmentami w odpowiednich plikach, aby wiedzieć, gdzie umieścić swój kod.
### Przygotowanie elementów do manipulacji w rozszerzeniu:
Do tej pory stworzyłeś HTML dla formularza i `
` wyników w swoim rozszerzeniu przeglądarki. Od teraz będziesz pracować w pliku `/src/index.js` i budować swoje rozszerzenie krok po kroku. Odwołaj się do [poprzedniej lekcji](../1-about-browsers/README.md), aby przypomnieć sobie, jak skonfigurować projekt i proces budowania.
Pracując w pliku `index.js`, zacznij od utworzenia kilku zmiennych `const`, które będą przechowywać wartości związane z różnymi polami:
```JavaScript
// form fields
const form = document.querySelector('.form-data');
const region = document.querySelector('.region-name');
const apiKey = document.querySelector('.api-key');
// results
const errors = document.querySelector('.errors');
const loading = document.querySelector('.loading');
const results = document.querySelector('.result-container');
const usage = document.querySelector('.carbon-usage');
const fossilfuel = document.querySelector('.fossil-fuel');
const myregion = document.querySelector('.my-region');
const clearBtn = document.querySelector('.clear-btn');
```
Wszystkie te pola są odwoływane za pomocą ich klas CSS, które ustawiłeś w HTML w poprzedniej lekcji.
### Dodaj nasłuchiwacze zdarzeń
Następnie dodaj nasłuchiwacze zdarzeń do formularza i przycisku czyszczenia, który resetuje formularz, aby coś się działo, gdy użytkownik przesyła formularz lub klika przycisk resetowania. Na końcu pliku dodaj wywołanie funkcji inicjalizującej aplikację:
```JavaScript
form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
init();
```
✅ Zwróć uwagę na skróconą metodę nasłuchiwania zdarzeń submit lub click oraz na to, jak zdarzenie jest przekazywane do funkcji handleSubmit lub reset. Czy potrafisz napisać równoważny kod w dłuższym formacie? Który sposób preferujesz?
### Rozbudowa funkcji init() i reset():
Teraz zbudujesz funkcję inicjalizującą rozszerzenie, nazwaną init():
```JavaScript
function init() {
//if anything is in localStorage, pick it up
const storedApiKey = localStorage.getItem('apiKey');
const storedRegion = localStorage.getItem('regionName');
//set icon to be generic green
//todo
if (storedApiKey === null || storedRegion === null) {
//if we don't have the keys, show the form
form.style.display = 'block';
results.style.display = 'none';
loading.style.display = 'none';
clearBtn.style.display = 'none';
errors.textContent = '';
} else {
//if we have saved keys/regions in localStorage, show results when they load
displayCarbonUsage(storedApiKey, storedRegion);
results.style.display = 'none';
form.style.display = 'none';
clearBtn.style.display = 'block';
}
};
function reset(e) {
e.preventDefault();
//clear local storage for region only
localStorage.removeItem('regionName');
init();
}
```
W tej funkcji znajduje się interesująca logika. Czytając ją, możesz zauważyć, co się dzieje:
- ustawiane są dwie zmienne `const`, które sprawdzają, czy użytkownik przechował APIKey i kod regionu w lokalnej pamięci.
- jeśli którakolwiek z tych wartości jest null, formularz jest wyświetlany poprzez zmianę jego stylu na 'block'.
- ukrywane są wyniki, komunikat ładowania oraz clearBtn, a tekst błędu jest ustawiany na pusty ciąg znaków.
- jeśli istnieje klucz i region, rozpoczyna się procedura:
- wywołanie API w celu uzyskania danych o zużyciu węgla,
- ukrycie obszaru wyników,
- ukrycie formularza,
- wyświetlenie przycisku resetowania.
Zanim przejdziesz dalej, warto dowiedzieć się o bardzo ważnym koncepcie dostępnym w przeglądarkach: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage). LocalStorage to przydatny sposób przechowywania ciągów znaków w przeglądarce jako pary `klucz-wartość`. Ten typ pamięci internetowej może być manipulowany za pomocą JavaScriptu w celu zarządzania danymi w przeglądarce. LocalStorage nie wygasa, podczas gdy SessionStorage, inny rodzaj pamięci internetowej, jest czyszczony po zamknięciu przeglądarki. Różne typy pamięci mają swoje zalety i wady.
> Uwaga - Twoje rozszerzenie przeglądarki ma własną lokalną pamięć; główne okno przeglądarki to inna instancja i działa niezależnie.
Ustawiasz wartość APIKey jako ciąg znaków, na przykład, i możesz zobaczyć, że jest ustawiona w Edge, "inspekcjonując" stronę internetową (możesz kliknąć prawym przyciskiem myszy w przeglądarce, aby inspekcjonować) i przechodząc do zakładki Applications, aby zobaczyć pamięć.

✅ Zastanów się nad sytuacjami, w których NIE chciałbyś przechowywać danych w LocalStorage. Ogólnie rzecz biorąc, umieszczanie kluczy API w LocalStorage to zły pomysł! Czy widzisz dlaczego? W naszym przypadku, ponieważ nasza aplikacja jest wyłącznie do nauki i nie będzie publikowana w sklepie z aplikacjami, użyjemy tej metody.
Zauważ, że używasz Web API do manipulowania LocalStorage, korzystając z `getItem()`, `setItem()` lub `removeItem()`. Jest szeroko wspierane w przeglądarkach.
Zanim zbudujesz funkcję `displayCarbonUsage()`, która jest wywoływana w `init()`, stwórz funkcjonalność obsługującą początkowe przesłanie formularza.
### Obsługa przesłania formularza
Utwórz funkcję nazwaną `handleSubmit`, która akceptuje argument zdarzenia `(e)`. Zatrzymaj propagację zdarzenia (w tym przypadku chcemy zatrzymać odświeżanie przeglądarki) i wywołaj nową funkcję `setUpUser`, przekazując argumenty `apiKey.value` i `region.value`. W ten sposób używasz dwóch wartości, które są wprowadzone za pomocą początkowego formularza, gdy odpowiednie pola są wypełnione.
```JavaScript
function handleSubmit(e) {
e.preventDefault();
setUpUser(apiKey.value, region.value);
}
```
✅ Przypomnij sobie - HTML, który ustawiłeś w ostatniej lekcji, ma dwa pola wejściowe, których `values` są przechwytywane za pomocą `const`, które ustawiłeś na początku pliku, i oba są `required`, więc przeglądarka uniemożliwia użytkownikom wprowadzenie wartości null.
### Konfiguracja użytkownika
Przechodząc do funkcji `setUpUser`, tutaj ustawiasz wartości lokalnej pamięci dla apiKey i regionName. Dodaj nową funkcję:
```JavaScript
function setUpUser(apiKey, regionName) {
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('regionName', regionName);
loading.style.display = 'block';
errors.textContent = '';
clearBtn.style.display = 'block';
//make initial call
displayCarbonUsage(apiKey, regionName);
}
```
Ta funkcja ustawia komunikat ładowania, który jest wyświetlany podczas wywoływania API. W tym momencie dotarłeś do stworzenia najważniejszej funkcji tego rozszerzenia przeglądarki!
### Wyświetlanie zużycia węgla
W końcu nadszedł czas na zapytanie API!
Zanim przejdziesz dalej, powinniśmy omówić API. API, czyli [Interfejsy Programowania Aplikacji](https://www.webopedia.com/TERM/A/API.html), są kluczowym elementem narzędzi web developera. Zapewniają standardowe sposoby interakcji i komunikacji między programami. Na przykład, jeśli budujesz stronę internetową, która musi zapytać bazę danych, ktoś mógł stworzyć API, które możesz użyć. Chociaż istnieje wiele typów API, jednym z najpopularniejszych jest [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
✅ Termin 'REST' oznacza 'Representational State Transfer' i polega na używaniu różnie skonfigurowanych URL do pobierania danych. Zrób małe badania na temat różnych typów API dostępnych dla programistów. Który format najbardziej Ci odpowiada?
Istnieją ważne rzeczy do zauważenia w tej funkcji. Po pierwsze, zwróć uwagę na słowo kluczowe [`async`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Pisanie funkcji tak, aby działały asynchronicznie, oznacza, że czekają na zakończenie akcji, takiej jak zwrócenie danych, zanim przejdą dalej.
Oto krótki film o `async`:
[](https://youtube.com/watch?v=YwmlRkrxvkk "Async i Await do zarządzania obietnicami")
> 🎥 Kliknij obrazek powyżej, aby obejrzeć film o async/await.
Utwórz nową funkcję do zapytania API C02Signal:
```JavaScript
import axios from '../node_modules/axios';
async function displayCarbonUsage(apiKey, region) {
try {
await axios
.get('https://api.co2signal.com/v1/latest', {
params: {
countryCode: region,
},
headers: {
'auth-token': apiKey,
},
})
.then((response) => {
let CO2 = Math.floor(response.data.data.carbonIntensity);
//calculateColor(CO2);
loading.style.display = 'none';
form.style.display = 'none';
myregion.textContent = region;
usage.textContent =
Math.round(response.data.data.carbonIntensity) + ' grams (grams C02 emitted per kilowatt hour)';
fossilfuel.textContent =
response.data.data.fossilFuelPercentage.toFixed(2) +
'% (percentage of fossil fuels used to generate electricity)';
results.style.display = 'block';
});
} catch (error) {
console.log(error);
loading.style.display = 'none';
results.style.display = 'none';
errors.textContent = 'Sorry, we have no data for the region you have requested.';
}
}
```
To duża funkcja. Co się tutaj dzieje?
- zgodnie z najlepszymi praktykami używasz słowa kluczowego `async`, aby funkcja działała asynchronicznie. Funkcja zawiera blok `try/catch`, ponieważ zwróci obietnicę, gdy API zwróci dane. Ponieważ nie masz kontroli nad szybkością odpowiedzi API (może w ogóle nie odpowiedzieć!), musisz obsłużyć tę niepewność, wywołując ją asynchronicznie.
- zapytujesz API co2signal, aby uzyskać dane dla swojego regionu, używając swojego klucza API. Aby użyć tego klucza, musisz użyć rodzaju uwierzytelnienia w parametrach nagłówka.
- gdy API odpowie, przypisujesz różne elementy jego danych odpowiedzi do części ekranu, które ustawiłeś, aby wyświetlać te dane.
- jeśli wystąpi błąd lub nie ma wyniku, wyświetlasz komunikat o błędzie.
✅ Korzystanie z wzorców programowania asynchronicznego to kolejny bardzo przydatny element w Twoim zestawie narzędzi. Przeczytaj [o różnych sposobach](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function), w jakie możesz skonfigurować tego typu kod.
Gratulacje! Jeśli zbudujesz swoje rozszerzenie (`npm run build`) i odświeżysz je w panelu rozszerzeń, masz działające rozszerzenie! Jedyną rzeczą, która nie działa, jest ikona, którą naprawisz w następnej lekcji.
---
## 🚀 Wyzwanie
Omówiliśmy kilka typów API w tych lekcjach. Wybierz jedno API internetowe i zbadaj szczegółowo, co oferuje. Na przykład, przyjrzyj się API dostępnemu w przeglądarkach, takim jak [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API). Co według Ciebie czyni API świetnym?
## Quiz po lekcji
[Quiz po lekcji](https://ff-quizzes.netlify.app/web/quiz/26)
## Przegląd i samodzielna nauka
W tej lekcji nauczyłeś się o LocalStorage i API, które są bardzo przydatne dla profesjonalnego web developera. Czy potrafisz pomyśleć, jak te dwie rzeczy współpracują? Zastanów się, jak zaprojektowałbyś stronę internetową, która przechowuje elementy do wykorzystania przez API.
## Zadanie
[Zaadoptuj API](assignment.md)
---
**Zastrzeżenie**:
Ten dokument został przetłumaczony za pomocą usługi tłumaczenia AI [Co-op Translator](https://github.com/Azure/co-op-translator). Chociaż dokładamy wszelkich starań, aby tłumaczenie było precyzyjne, prosimy pamiętać, że automatyczne tłumaczenia mogą zawierać błędy lub nieścisłości. Oryginalny dokument w jego rodzimym języku powinien być uznawany za autorytatywne źródło. W przypadku informacji o kluczowym znaczeniu zaleca się skorzystanie z profesjonalnego tłumaczenia przez człowieka. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z użycia tego tłumaczenia.