You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/nl/5-browser-extension/2-forms-browsers-local-storage/README.md

20 KiB

Browserextensieproject Deel 2: Een API aanroepen, gebruik maken van Local Storage

Quiz voor de les

Quiz voor de les

Introductie

Weet je nog die browserextensie die je bent begonnen te bouwen? Op dit moment heb je een mooi ogend formulier, maar het is eigenlijk statisch. Vandaag gaan we het tot leven brengen door het te verbinden met echte gegevens en het geheugen te geven.

Denk aan de Apollo-missiecontrolecomputers - ze gaven niet alleen vaste informatie weer. Ze communiceerden voortdurend met ruimtevaartuigen, werkten bij met telemetriegegevens en onthielden kritieke missieparameters. Dat is het soort dynamisch gedrag dat we vandaag gaan bouwen. Jouw extensie zal verbinding maken met het internet, echte milieugegevens ophalen en jouw instellingen onthouden voor de volgende keer.

API-integratie klinkt misschien ingewikkeld, maar het is eigenlijk gewoon je code leren communiceren met andere diensten. Of je nu weergegevens, sociale mediafeeds of informatie over de ecologische voetafdruk ophaalt, zoals we vandaag gaan doen, het draait allemaal om het tot stand brengen van deze digitale verbindingen. We zullen ook onderzoeken hoe browsers informatie kunnen bewaren - vergelijkbaar met hoe bibliotheken kaartenbakken hebben gebruikt om te onthouden waar boeken thuishoren.

Aan het einde van deze les heb je een browserextensie die echte gegevens ophaalt, gebruikersvoorkeuren opslaat en een soepele ervaring biedt. Laten we beginnen!

Volg de genummerde segmenten in de juiste bestanden om te weten waar je je code moet plaatsen.

Stel de elementen in om te manipuleren in de extensie

Voordat je JavaScript de interface kan manipuleren, heeft het referenties naar specifieke HTML-elementen nodig. Denk eraan als een telescoop die op bepaalde sterren gericht moet worden - voordat Galileo de manen van Jupiter kon bestuderen, moest hij Jupiter zelf lokaliseren en erop focussen.

In je index.js-bestand maken we const-variabelen die referenties vastleggen naar elk belangrijk formelement. Dit is vergelijkbaar met hoe wetenschappers hun apparatuur labelen - in plaats van elke keer door het hele laboratorium te zoeken, kunnen ze direct toegang krijgen tot wat ze nodig hebben.

// 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');

Wat deze code doet:

  • Vastleggen van formelementen met behulp van document.querySelector() en CSS-klasse-selectors
  • Creëren van referenties naar invoervelden voor de regio-naam en API-sleutel
  • Opzetten van verbindingen met resultaatweergeven elementen voor gegevens over koolstofgebruik
  • Toegang instellen tot UI-elementen zoals laadindicatoren en foutmeldingen
  • Opslaan van elke elementreferentie in een const-variabele voor eenvoudig hergebruik in je code

Voeg event listeners toe

Nu gaan we ervoor zorgen dat je extensie reageert op gebruikersacties. Event listeners zijn de manier waarop je code gebruikersinteracties in de gaten houdt. Denk aan ze als de operators in vroege telefooncentrales - ze luisterden naar inkomende oproepen en verbonden de juiste circuits wanneer iemand een verbinding wilde maken.

form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
init();

Begrijp deze concepten:

  • Bevestigt een submit listener aan het formulier die wordt geactiveerd wanneer gebruikers op Enter drukken of op verzenden klikken
  • Verbindt een kliklistener aan de knop 'wissen' om het formulier opnieuw in te stellen
  • Geeft het event-object (e) door aan handlerfuncties voor extra controle
  • Roept de init()-functie onmiddellijk aan om de initiële status van je extensie in te stellen

Let op de korte pijlfunctie-syntaxis die hier wordt gebruikt. Deze moderne JavaScript-aanpak is overzichtelijker dan traditionele functie-expressies, maar beide werken even goed!

Bouw de initialisatie- en resetfuncties

Laten we de initialisatielogica voor je extensie maken. De init()-functie is als het navigatiesysteem van een schip dat zijn instrumenten controleert - het bepaalt de huidige status en past de interface dienovereenkomstig aan. Het controleert of iemand je extensie eerder heeft gebruikt en laadt hun eerdere instellingen.

De reset()-functie biedt gebruikers een frisse start - vergelijkbaar met hoe wetenschappers hun instrumenten tussen experimenten resetten om schone gegevens te garanderen.

function init() {
	// Check if user has previously saved API credentials
	const storedApiKey = localStorage.getItem('apiKey');
	const storedRegion = localStorage.getItem('regionName');

	// Set extension icon to generic green (placeholder for future lesson)
	// TODO: Implement icon update in next lesson

	if (storedApiKey === null || storedRegion === null) {
		// First-time user: show the setup form
		form.style.display = 'block';
		results.style.display = 'none';
		loading.style.display = 'none';
		clearBtn.style.display = 'none';
		errors.textContent = '';
	} else {
		// Returning user: load their saved data automatically
		displayCarbonUsage(storedApiKey, storedRegion);
		results.style.display = 'none';
		form.style.display = 'none';
		clearBtn.style.display = 'block';
	}
}

function reset(e) {
	e.preventDefault();
	// Clear stored region to allow user to choose a new location
	localStorage.removeItem('regionName');
	// Restart the initialization process
	init();
}

Wat hier gebeurt:

  • Haalt opgeslagen API-sleutel en regio op uit de lokale opslag van de browser
  • Controleert of dit een nieuwe gebruiker is (geen opgeslagen gegevens) of een terugkerende gebruiker
  • Toont het instellingsformulier voor nieuwe gebruikers en verbergt andere interface-elementen
  • Laadt automatisch opgeslagen gegevens voor terugkerende gebruikers en toont de resetoptie
  • Beheert de status van de gebruikersinterface op basis van beschikbare gegevens

Belangrijke concepten over Local Storage:

  • Bewaren van gegevens tussen browsersessies (in tegenstelling tot sessieopslag)
  • Opslaan van gegevens als sleutel-waardeparen met behulp van getItem() en setItem()
  • Geeft null terug wanneer er geen gegevens bestaan voor een bepaalde sleutel
  • Biedt een eenvoudige manier om gebruikersvoorkeuren en instellingen te onthouden

💡 Begrip van Browseropslag: LocalStorage is als het geven van persistent geheugen aan je extensie. Denk aan hoe de oude Bibliotheek van Alexandrië rollen opsloeg - informatie bleef beschikbaar, zelfs wanneer geleerden vertrokken en terugkwamen.

Belangrijke kenmerken:

  • Bewaren van gegevens, zelfs nadat je je browser sluit
  • Overleven van computerherstarts en browsercrashes
  • Bieden van aanzienlijke opslagruimte voor gebruikersvoorkeuren
  • Directe toegang zonder netwerkvertragingen

Belangrijke opmerking: Je browserextensie heeft zijn eigen geïsoleerde lokale opslag die gescheiden is van gewone webpagina's. Dit biedt veiligheid en voorkomt conflicten met andere websites.

Je kunt je opgeslagen gegevens bekijken door de ontwikkelaarstools van de browser te openen (F12), naar het tabblad Application te gaan en de sectie Local Storage uit te vouwen.

Local storage pane

⚠️ Veiligheidsoverweging: In productie-applicaties brengt het opslaan van API-sleutels in LocalStorage beveiligingsrisico's met zich mee, omdat JavaScript toegang heeft tot deze gegevens. Voor leerdoeleinden werkt deze aanpak prima, maar echte applicaties zouden veilige server-side opslag moeten gebruiken voor gevoelige gegevens.

Verwerk formulierinzending

Nu gaan we verwerken wat er gebeurt wanneer iemand je formulier indient. Standaard herladen browsers de pagina wanneer formulieren worden ingediend, maar we zullen dit gedrag onderscheppen om een soepelere ervaring te creëren.

Deze aanpak weerspiegelt hoe missiecontrole omgaat met communicatie van ruimtevaartuigen - in plaats van het hele systeem opnieuw in te stellen voor elke transmissie, behouden ze continue werking terwijl ze nieuwe informatie verwerken.

Maak een functie die het formulierinzendingsevenement vastlegt en de invoer van de gebruiker extraheert:

function handleSubmit(e) {
	e.preventDefault();
	setUpUser(apiKey.value, region.value);
}

In het bovenstaande hebben we:

  • Voorkomen van het standaardgedrag van formulierinzending dat de pagina zou verversen
  • Extraheert gebruikersinvoergegevens uit de API-sleutel- en regiovelden
  • Geeft de formuliergegevens door aan de setUpUser()-functie voor verwerking
  • Behoudt single-page applicatiegedrag door paginaherlaadacties te vermijden

Onthoud dat je HTML-formuliervelden het required-attribuut bevatten, zodat de browser automatisch valideert dat gebruikers zowel de API-sleutel als de regio opgeven voordat deze functie wordt uitgevoerd.

Stel gebruikersvoorkeuren in

De setUpUser-functie is verantwoordelijk voor het opslaan van de gebruikersgegevens en het initiëren van de eerste API-aanroep. Dit zorgt voor een soepele overgang van de setup naar het weergeven van resultaten.

function setUpUser(apiKey, regionName) {
	// Save user credentials for future sessions
	localStorage.setItem('apiKey', apiKey);
	localStorage.setItem('regionName', regionName);
	
	// Update UI to show loading state
	loading.style.display = 'block';
	errors.textContent = '';
	clearBtn.style.display = 'block';
	
	// Fetch carbon usage data with user's credentials
	displayCarbonUsage(apiKey, regionName);
}

Stap voor stap, wat hier gebeurt:

  • Slaat de API-sleutel en regiocode op in de lokale opslag voor toekomstig gebruik
  • Toont een laadindicator om gebruikers te informeren dat gegevens worden opgehaald
  • Verwijdert eventuele eerdere foutmeldingen van de weergave
  • Toont de knop 'wissen' zodat gebruikers hun instellingen later kunnen resetten
  • Start de API-aanroep om echte gegevens over koolstofgebruik op te halen

Deze functie creëert een naadloze gebruikerservaring door zowel gegevensopslag als gebruikersinterface-updates in één gecoördineerde actie te beheren.

Toon gegevens over koolstofgebruik

Nu gaan we je extensie verbinden met externe gegevensbronnen via APIs. Dit transformeert je extensie van een op zichzelf staande tool naar iets dat toegang heeft tot realtime informatie van over het hele internet.

Begrip van APIs

APIs zijn hoe verschillende applicaties met elkaar communiceren. Denk aan ze als het telegraafsysteem dat in de 19e eeuw verre steden met elkaar verbond - operators stuurden verzoeken naar verre stations en ontvingen antwoorden met de gevraagde informatie. Elke keer dat je sociale media controleert, een vraag stelt aan een spraakassistent of een bezorgapp gebruikt, faciliteren APIs deze gegevensuitwisselingen.

Belangrijke concepten over REST APIs:

  • REST staat voor 'Representational State Transfer'
  • Gebruikt standaard HTTP-methoden (GET, POST, PUT, DELETE) om met gegevens te werken
  • Geeft gegevens terug in voorspelbare formaten, meestal JSON
  • Biedt consistente, URL-gebaseerde eindpunten voor verschillende soorten verzoeken

De CO2 Signal API die we gaan gebruiken biedt realtime gegevens over koolstofintensiteit van elektriciteitsnetten wereldwijd. Dit helpt gebruikers de milieueffecten van hun elektriciteitsgebruik te begrijpen!

💡 Begrip van Asynchrone JavaScript: Het async-keyword stelt je code in staat om meerdere operaties tegelijkertijd te verwerken. Wanneer je gegevens van een server opvraagt, wil je niet dat je hele extensie vastloopt - dat zou zijn alsof luchtverkeersleiding alle operaties stopt terwijl ze wachten op één vliegtuig om te reageren.

Belangrijke voordelen:

  • Behoudt de responsiviteit van de extensie terwijl gegevens worden geladen
  • Staat andere code toe om door te gaan met uitvoeren tijdens netwerkverzoeken
  • Verbetert de leesbaarheid van code in vergelijking met traditionele callbackpatronen
  • Maakt gracieus foutbeheer mogelijk bij netwerkproblemen

Hier is een korte video over async:

Async en Await voor het beheren van promises

🎥 Klik op de afbeelding hierboven voor een video over async/await.

Maak de functie om gegevens over koolstofgebruik op te halen en weer te geven:

// Modern fetch API approach (no external dependencies needed)
async function displayCarbonUsage(apiKey, region) {
	try {
		// Fetch carbon intensity data from CO2 Signal API
		const response = await fetch('https://api.co2signal.com/v1/latest', {
			method: 'GET',
			headers: {
				'auth-token': apiKey,
				'Content-Type': 'application/json'
			},
			// Add query parameters for the specific region
			...new URLSearchParams({ countryCode: region }) && {
				url: `https://api.co2signal.com/v1/latest?countryCode=${region}`
			}
		});

		// Check if the API request was successful
		if (!response.ok) {
			throw new Error(`API request failed: ${response.status}`);
		}

		const data = await response.json();
		const carbonData = data.data;

		// Calculate rounded carbon intensity value
		const carbonIntensity = Math.round(carbonData.carbonIntensity);

		// Update the user interface with fetched data
		loading.style.display = 'none';
		form.style.display = 'none';
		myregion.textContent = region.toUpperCase();
		usage.textContent = `${carbonIntensity} grams (grams CO₂ emitted per kilowatt hour)`;
		fossilfuel.textContent = `${carbonData.fossilFuelPercentage.toFixed(2)}% (percentage of fossil fuels used to generate electricity)`;
		results.style.display = 'block';

		// TODO: calculateColor(carbonIntensity) - implement in next lesson

	} catch (error) {
		console.error('Error fetching carbon data:', error);
		
		// Show user-friendly error message
		loading.style.display = 'none';
		results.style.display = 'none';
		errors.textContent = 'Sorry, we couldn\'t fetch data for that region. Please check your API key and region code.';
	}
}

Wat hier gebeurt:

  • Gebruikt de moderne fetch() API in plaats van externe bibliotheken zoals Axios voor schonere, afhankelijkheidsvrije code
  • Implementeert correcte foutcontrole met response.ok om API-fouten vroegtijdig op te vangen
  • Behandelt asynchrone operaties met async/await voor een meer leesbare codeflow
  • Authenticeert met de CO2 Signal API via de auth-token header
  • Parseert JSON-reactiegegevens en extraheert informatie over koolstofintensiteit
  • Update meerdere UI-elementen met geformatteerde milieugegevens
  • Biedt gebruiksvriendelijke foutmeldingen wanneer API-aanroepen mislukken

Belangrijke moderne JavaScript-concepten die worden gedemonstreerd:

  • Template literals met ${}-syntaxis voor schone stringopmaak
  • Foutbeheer met try/catch-blokken voor robuuste applicaties
  • Async/await-patroon voor gracieus omgaan met netwerkverzoeken
  • Object destructuring om specifieke gegevens uit API-reacties te halen
  • Method chaining voor meerdere DOM-manipulaties

Deze functie demonstreert verschillende belangrijke webontwikkelingsconcepten - communiceren met externe servers, omgaan met authenticatie, gegevens verwerken, interfaces bijwerken en fouten gracieus beheren. Dit zijn fundamentele vaardigheden die professionele ontwikkelaars regelmatig gebruiken.

🎉 Wat je hebt bereikt: Je hebt een browserextensie gemaakt die:

  • Verbindt met het internet en echte milieugegevens ophaalt
  • Bewaren van gebruikersinstellingen tussen sessies
  • Behandelt fouten gracieus in plaats van te crashen
  • Biedt een soepele, professionele gebruikerservaring

Test je werk door npm run build uit te voeren en je extensie in de browser te vernieuwen. Je hebt nu een functionele tracker voor de ecologische voetafdruk. De volgende les voegt dynamische pictogramfunctionaliteit toe om de extensie compleet te maken.


GitHub Copilot Agent Challenge 🚀

Gebruik de Agent-modus om de volgende uitdaging te voltooien:

Beschrijving: Verbeter de browserextensie door foutafhandelingsverbeteringen en gebruikerservaringsfuncties toe te voegen. Deze uitdaging helpt je oefenen met het werken met APIs, lokale opslag en DOM-manipulatie met moderne JavaScript-patronen.

Prompt: Maak een verbeterde versie van de displayCarbonUsage-functie die het volgende bevat: 1) Een retry-mechanisme voor mislukte API-aanroepen met exponentiële backoff, 2) Invoervalidatie voor de regiocode voordat de API-aanroep wordt gedaan, 3) Een laadanimatie met voortgangsindicatoren, 4) Caching van API-reacties in localStorage met vervaltijdstempels (cache voor 30 minuten), en 5) Een functie om historische gegevens van eerdere API-aanroepen weer te geven. Voeg ook correcte TypeScript-stijl JSDoc-commentaar toe om alle functieparameters en retourtypes te documenteren.

Meer informatie over agent mode vind je hier.

🚀 Uitdaging

Breid je begrip van APIs uit door de rijkdom aan browsergebaseerde APIs te verkennen die beschikbaar zijn voor webontwikkeling. Kies een van deze browser-APIs en bouw een kleine demonstratie:

Onderzoeksvragen om te overwegen:

  • Welke problemen in de echte wereld lost deze API op?
  • Hoe gaat de API om met fouten en randgevallen?
  • Welke veiligheidsaspecten zijn er bij het gebruik van deze API?
  • Hoe breed wordt deze API ondersteund door verschillende browsers?

Na je onderzoek, identificeer welke kenmerken een API gebruiksvriendelijk en betrouwbaar maken.

Quiz na de les

Quiz na de les

Review & Zelfstudie

Je hebt in deze les geleerd over LocalStorage en API's, beide erg nuttig voor de professionele webontwikkelaar. Kun je bedenken hoe deze twee dingen samenwerken? Denk na over hoe je een website zou ontwerpen die items opslaat om te worden gebruikt door een API.

Opdracht

Adopteer een API


Disclaimer:
Dit document is vertaald met behulp van de AI-vertalingsservice Co-op Translator. Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor kritieke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor eventuele misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.