Должен закодировать их всех!

Введение

Проходя курс обучения веб-разработчиков полного цикла Flatiron School, я наконец-то добрался до первой задачи программы: разработки одностраничного веб-приложения на Javascript, HTML и CSS с нуля. Хотя я колебался между несколькими разными идеями о том, что создать для своего приложения, я в конце концов решил сделать приложение на основе Pokédex, инструмента из франшизы Pokémon, который используется для отслеживания каждого покемона, пойманного человеком.

Доступ к данным о покемонах

Чтобы соответствовать требованиям этого проекта, приложению необходимо получить доступ к данным из API или локальной базы данных и отобразить на странице не менее пяти элементов с тремя свойствами каждый. Чтобы выполнить эти требования, я хочу отобразить всех исходных 151 покемонов с их именем, изображением, статусом того, пойман ли покемон или нет, и псевдонимом, созданным пользователем. К счастью, PokéAPI предоставляет надежный набор данных с подробными записями о каждом из более чем 1000 существующих сегодня покемонов. Из этого API я решил получить имя и изображение для каждой карты покемонов, которые будут отображаться на странице. Однако PokéAPI не предоставляет конечной точки для получения всех данных о покемонах с помощью одного запроса на выборку, поэтому мне нужно найти другой метод для выполнения моей задачи.

Проводя исследования в Интернете, я нашел один реальный способ получить все данные о покемонах одновременно: Promise.all. Обещание в Javascript — это объект, возвращаемый запросом на выборку, который, согласно MDN, представляет возможное завершение (или сбой) асинхронной операции и ее результирующее значение. Promise.all — это метод, который выполняет несколько промисов параллельно и сразу возвращает список ответов. Итак, чтобы получить данные для первого 151 покемона, я повторил цикл for, добавляя возвращаемое значение каждого запроса на выборку в массив:

let promises = [];
for(let i = 0; i < 151; i++) {
  promises.push(fetch(`https://pokeapi.co/api/v2/pokemon/${i+1}`)
  .then(response => response.json()));
}

Затем я вызвал функцию Promise.all, передав ей в качестве аргумента массив обещаний. Используя метод forEach, я создал объект Pokémon с данными из каждого объекта json, возвращаемого из метода Promises.all.

Promise.all(promises)
.then(results => results.forEach(pokemonObj => {
    let pokemon = {
        name:pokemonObj.name,
        id: pokemonObj.id,
        image: pokemonObj.sprites.front_default,
        caught:false,
        nickname:""
    }

С помощью простого вызова console.log я смог подтвердить, что данные были успешно извлечены из API! Когда первый трудоемкий этап создания этого приложения завершен, пришло время фактически отобразить полученные данные. К счастью, все, что последовало за этим, было гораздо проще.

Отображение данных

Поскольку я хотел, чтобы статус и псевдоним пойманного покемона сохранялись после обновления страницы, я решил добавить данные о покемонах с помощью почтовых запросов в локальный файл db.json, из которого мое приложение могло читать. Затем мне нужно было отобразить каждую карту покемонов на странице. Для этого достаточно было просто создать объекты элементов DOM для каждого атрибута и добавить их в DOM. Чтобы пользователь мог отметить, поймал ли он покемона или нет, я сделал кнопку, при нажатии которой свойство «поймал» в базе данных менялось на true. Текст кнопки изменится с «Добавить в Pokédex» на «Поймал!» после щелчка, и это изменение исправлено в файле db.json. Кроме того, цвет фона карты меняется на зеленый.

card.querySelector('.caught-btn').addEventListener('click', (e) => {
        pokemon.caught = true;
        /* Patch request to update 'caught' status in db */
        updatePokemon(pokemon, {"caught":pokemon.caught})
        .then((pokemonData) => {
            card.querySelector('.caught-btn').disabled = true;
            card.querySelector('.caught-btn').innerText = "Caught!";
            card.style["background-color"] = "#caedcc";
        });
    }); 

Наконец, чтобы добавить функциональность создания псевдонимов, я добавил активную гиперссылку, которая вызывала текстовое поле при нажатии. Если ввести текстовое поле и отправить его, этот текст будет сохранен как псевдоним покемона. Этот псевдоним будет сохранен в локальной базе данных с помощью запроса на исправление, что позволит ему сохраняться при обновлении страницы.

/* Handles form submission and updating of both DOM and database */
form.addEventListener('submit', (e) => {
        e.preventDefault();

        updatePokemon(pokemon, {"nickname":e.target.nickname.value})
        .then((pokemonData) => {
            /* Function to add nickname to the DOM */
            setNickname(pokemonData, pokeNickname, form, removeHyperlink, addHyperlink);
        })     
    })

После добавления стилей в CSS конечный продукт выглядел так:

А вот пример с пойманными покемонами и добавленными никнеймами:

Заключение

В конце концов, хотя я и доволен тем, как получился проект, я все еще чувствую, что есть много улучшений, которые можно было бы сделать, чтобы сделать его более надежным приложением. Я планирую улучшить стиль, добавить больше атрибутов для каждой карты покемонов и, в конечном итоге, развернуть ее в Интернете. Из-за нехватки времени я не смог добавить все эти функции, но в будущем время для их реализации будет. Этот проект был полезен для изучения промисов в Javascript, а также для применения на практике всего, что я узнал до сих пор с помощью программы Full-Stack Web Developer. Работа над этим проектом, безусловно, была хорошим обучающим процессом, но теперь пришло время перейти к следующему!

Ссылка на гитхаб: https://github.com/aadilahmed/phase-1-project-my-pokedex