27 KiB
Проєкт розширення для браузера, частина 2: Використання API, локальне збереження даних
Тест перед лекцією
Вступ
Пам'ятаєте розширення для браузера, яке ви почали створювати? Зараз у вас є гарна форма, але вона поки що статична. Сьогодні ми оживимо її, підключивши до реальних даних і додавши пам'ять.
Згадайте комп'ютери управління місією Apollo — вони не просто показували фіксовану інформацію. Вони постійно спілкувалися з космічними апаратами, оновлювали дані телеметрії та запам'ятовували важливі параметри місії. Саме таку динамічну поведінку ми створюємо сьогодні. Ваше розширення буде звертатися до інтернету, отримувати реальні дані про навколишнє середовище і запам'ятовувати ваші налаштування для наступного використання.
Інтеграція API може здаватися складною, але насправді це просто навчання вашого коду спілкуватися з іншими сервісами. Незалежно від того, чи ви отримуєте дані про погоду, стрічки соціальних мереж або інформацію про вуглецевий слід, як ми зробимо сьогодні, все це зводиться до встановлення цифрових зв'язків. Ми також дослідимо, як браузери можуть зберігати інформацію — подібно до того, як бібліотеки використовували карткові каталоги для запам'ятовування місцезнаходження книг.
До кінця цього уроку у вас буде розширення для браузера, яке отримує реальні дані, зберігає налаштування користувача і забезпечує плавний досвід використання. Почнемо!
✅ Дотримуйтесь пронумерованих сегментів у відповідних файлах, щоб знати, де розміщувати ваш код.
Налаштування елементів для маніпуляції в розширенні
Перш ніж ваш JavaScript зможе маніпулювати інтерфейсом, йому потрібні посилання на конкретні HTML-елементи. Це як телескоп, який потрібно направити на певні зірки — перед тим, як Галілей міг вивчати супутники Юпітера, він повинен був знайти і сфокусуватися на самому Юпітері.
У вашому файлі index.js ми створимо змінні const, які захоплюють посилання на кожен важливий елемент форми. Це схоже на те, як вчені маркують своє обладнання — замість того, щоб кожного разу шукати по всій лабораторії, вони можуть безпосередньо отримати доступ до потрібного.
// 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');
Що робить цей код:
- Захоплює елементи форми за допомогою
document.querySelector()з CSS-селекторами класів - Створює посилання на поля введення для назви регіону та ключа API
- Встановлює зв'язки з елементами відображення результатів для даних про використання вуглецю
- Налаштовує доступ до елементів інтерфейсу, таких як індикатори завантаження та повідомлення про помилки
- Зберігає кожне посилання на елемент у змінній
constдля легкого повторного використання в коді
Додайте слухачі подій
Тепер ми зробимо так, щоб ваше розширення реагувало на дії користувача. Слухачі подій — це спосіб вашого коду стежити за взаємодіями користувача. Уявіть їх як операторів у ранніх телефонних станціях — вони слухали вхідні дзвінки і з'єднували правильні лінії, коли хтось хотів зробити дзвінок.
form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
init();
Розуміння цих концепцій:
- Прикріплює слухач подій до форми, який активується, коли користувачі натискають Enter або кнопку "Надіслати"
- З'єднує слухач кліків з кнопкою очищення для скидання форми
- Передає об'єкт події
(e)до функцій-обробників для додаткового контролю - Викликає функцію
init()негайно для налаштування початкового стану вашого розширення
✅ Зверніть увагу на скорочений синтаксис стрілкових функцій, який використовується тут. Цей сучасний підхід JavaScript є більш чистим, ніж традиційні вирази функцій, але обидва працюють однаково добре!
Створіть функції ініціалізації та скидання
Давайте створимо логіку ініціалізації для вашого розширення. Функція init() схожа на навігаційну систему корабля, яка перевіряє свої інструменти — вона визначає поточний стан і відповідно налаштовує інтерфейс. Вона перевіряє, чи хтось вже використовував ваше розширення, і завантажує його попередні налаштування.
Функція reset() надає користувачам можливість почати з чистого аркуша — подібно до того, як вчені скидають свої інструменти між експериментами, щоб забезпечити чистоту даних.
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();
}
Розбір того, що тут відбувається:
- Отримує збережений ключ API та регіон з локального сховища браузера
- Перевіряє, чи це перший раз, коли користувач використовує розширення (немає збережених даних), чи він повернувся
- Показує форму налаштування для нових користувачів і приховує інші елементи інтерфейсу
- Автоматично завантажує збережені дані для користувачів, які повернулися, і показує опцію скидання
- Керує станом інтерфейсу користувача на основі доступних даних
Ключові концепції про локальне сховище:
- Зберігає дані між сесіями браузера (на відміну від session storage)
- Зберігає дані у вигляді пар ключ-значення за допомогою
getItem()іsetItem() - Повертає
null, якщо дані для заданого ключа не існують - Надає простий спосіб запам'ятовувати налаштування та вподобання користувача
💡 Розуміння локального сховища браузера: LocalStorage — це як надання вашому розширенню постійної пам'яті. Уявіть, як стародавня бібліотека в Александрії зберігала сувої — інформація залишалася доступною навіть після того, як вчені залишали і поверталися.
Основні характеристики:
- Зберігає дані навіть після закриття браузера
- Переживає перезавантаження комп'ютера та аварії браузера
- Надає значний обсяг пам'яті для налаштувань користувача
- Забезпечує миттєвий доступ без затримок мережі
Важлива примітка: Ваше розширення для браузера має власне ізольоване локальне сховище, яке відокремлене від звичайних веб-сторінок. Це забезпечує безпеку і запобігає конфліктам з іншими веб-сайтами.
Ви можете переглянути збережені дані, відкривши інструменти розробника браузера (F12), перейшовши на вкладку Application і розгорнувши розділ Local Storage.
⚠️ Міркування щодо безпеки: У виробничих додатках зберігання ключів API у LocalStorage становить ризик для безпеки, оскільки JavaScript може отримати доступ до цих даних. Для навчальних цілей цей підхід підходить, але реальні додатки повинні використовувати безпечне серверне сховище для конфіденційних даних.
Обробка відправки форми
Тепер ми розглянемо, що відбувається, коли хтось надсилає вашу форму. За замовчуванням браузери перезавантажують сторінку при відправці форм, але ми перехопимо цю поведінку, щоб створити більш плавний досвід.
Цей підхід нагадує, як центр управління місією обробляє комунікації з космічними апаратами — замість того, щоб перезавантажувати всю систему для кожної передачі, вони підтримують безперервну роботу, обробляючи нову інформацію.
Створіть функцію, яка захоплює подію відправки форми і витягує введені користувачем дані:
function handleSubmit(e) {
e.preventDefault();
setUpUser(apiKey.value, region.value);
}
У наведеному вище коді ми:
- Запобігаємо стандартній поведінці відправки форми, яка б оновила сторінку
- Витягуємо значення, введені користувачем, з полів ключа API та регіону
- Передаємо дані форми до функції
setUpUser()для обробки - Підтримуємо поведінку односторінкового додатка, уникаючи перезавантаження сторінки
✅ Пам'ятайте, що ваші поля форми HTML включають атрибут required, тому браузер автоматично перевіряє, чи користувачі надали ключ API та регіон перед виконанням цієї функції.
Налаштування вподобань користувача
Функція setUpUser відповідає за збереження облікових даних користувача та ініціалізацію першого виклику API. Це створює плавний перехід від налаштування до відображення результатів.
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);
}
Крок за кроком, ось що відбувається:
- Зберігає ключ API та назву регіону в локальному сховищі для майбутнього використання
- Показує індикатор завантаження, щоб повідомити користувачів про отримання даних
- Очищає будь-які попередні повідомлення про помилки з дисплея
- Відображає кнопку очищення для користувачів, щоб вони могли скинути свої налаштування пізніше
- Ініціює виклик API для отримання реальних даних про використання вуглецю
Ця функція створює безперервний досвід користувача, керуючи як збереженням даних, так і оновленням інтерфейсу користувача в одному узгодженому дії.
Відображення даних про використання вуглецю
Тепер ми підключимо ваше розширення до зовнішніх джерел даних через API. Це перетворює ваше розширення з автономного інструмента на щось, що може отримувати інформацію в реальному часі з усього інтернету.
Розуміння API
API — це спосіб, яким різні додатки спілкуються один з одним. Уявіть їх як телеграфну систему, яка з'єднувала віддалені міста в 19 столітті — оператори надсилали запити до віддалених станцій і отримували відповіді з потрібною інформацією. Кожного разу, коли ви перевіряєте соціальні мережі, задаєте питання голосовому асистенту або використовуєте додаток для доставки, API забезпечують ці обміни даними.
Ключові концепції про REST API:
- REST означає "Representational State Transfer"
- Використовує стандартні HTTP-методи (GET, POST, PUT, DELETE) для взаємодії з даними
- Повертає дані у передбачуваних форматах, зазвичай JSON
- Надає послідовні URL-адреси для різних типів запитів
✅ API CO2 Signal, який ми будемо використовувати, надає дані про інтенсивність вуглецевих викидів в реальному часі з електромереж у всьому світі. Це допомагає користувачам зрозуміти вплив їхнього споживання електроенергії на навколишнє середовище!
💡 Розуміння асинхронного JavaScript: Ключове слово
asyncдозволяє вашому коду виконувати кілька операцій одночасно. Коли ви запитуєте дані з сервера, ви не хочете, щоб ваше розширення повністю зависло — це було б як зупинка всіх операцій авіадиспетчерської служби під час очікування відповіді одного літака.Основні переваги:
- Підтримує чутливість розширення під час завантаження даних
- Дозволяє іншому коду продовжувати виконання під час мережевих запитів
- Покращує читабельність коду порівняно з традиційними шаблонами зворотного виклику
- Забезпечує елегантне оброблення помилок для мережевих проблем
Ось коротке відео про async:
🎥 Натисніть на зображення вище, щоб переглянути відео про async/await.
Створіть функцію для отримання та відображення даних про використання вуглецю:
// 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.';
}
}
Розбір того, що відбувається тут:
- Використовує сучасний API
fetch()замість зовнішніх бібліотек, таких як Axios, для чистого коду без залежностей - Реалізує належну перевірку помилок за допомогою
response.ok, щоб рано виявляти збої API - Обробляє асинхронні операції за допомогою
async/awaitдля більш читабельного потоку коду - Аутентифікує за допомогою API CO2 Signal через заголовок
auth-token - Парсує JSON-відповідь і витягує інформацію про інтенсивність вуглецю
- Оновлює кілька елементів інтерфейсу користувача з відформатованими даними про навколишнє середовище
- Надає зручні для користувача повідомлення про помилки, коли виклики API не вдаються
Ключові сучасні концепції JavaScript, які демонструються:
- Шаблонні літерали з синтаксисом
${}для чистого форматування рядків - Обробка помилок за допомогою блоків try/catch для надійних додатків
- Шаблон async/await для елегантного управління мережевими запитами
- Деструктуризація об'єктів для витягу конкретних даних з відповідей API
- Ланцюжок методів для кількох маніпуляцій DOM
✅ Ця функція демонструє кілька важливих концепцій веб-розробки — спілкування з зовнішніми серверами, обробку аутентифікації, обробку даних, оновлення інтерфейсу та елегантне управління помилками. Це фундаментальні навички, які професійні розробники використовують регулярно.
🎉 Що ви досягли: Ви створили розширення для браузера, яке:
- Підключається до інтернету і отримує реальні дані про навколишнє середовище
- Зберігає налаштування користувача між сесіями
- Елегантно обробляє помилки, замість того щоб аварійно завершувати роботу
- Забезпечує плавний, професійний досвід користувача
Перевірте Ви дізналися про LocalStorage та API в цьому уроці, обидва дуже корисні для професійного веб-розробника. Чи можете ви подумати, як ці дві речі працюють разом? Подумайте, як би ви спроєктували веб-сайт, який зберігатиме елементи для використання API.
Завдання
Відмова від відповідальності:
Цей документ був перекладений за допомогою сервісу автоматичного перекладу Co-op Translator. Хоча ми прагнемо до точності, будь ласка, майте на увазі, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ на його рідній мові слід вважати авторитетним джерелом. Для критичної інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникають внаслідок використання цього перекладу.

