[{"data":1,"prerenderedAt":299},["ShallowReactive",2],{"blog-\u002Fpl\u002Fwpisy\u002F2024\u002Fpokedex-kilkadziesiat-zapytan-zamiast-tysiaca":3,"blog-project-\u002Fpl\u002Fwpisy\u002F2024\u002Fpokedex-kilkadziesiat-zapytan-zamiast-tysiaca":185},{"id":4,"title":5,"art":6,"body":7,"date":166,"description":167,"draft":168,"extension":169,"image":170,"kind":171,"meta":172,"navigation":173,"ogImage":174,"path":175,"project":176,"seo":177,"slug":170,"stem":178,"tags":179,"translationKey":183,"updated":170,"__hash__":184},"blog_pl\u002Fpl\u002Fwpisy\u002F2024\u002Fpokedex-kilkadziesiat-zapytan-zamiast-tysiaca.md","Pokedex – kilkadziesiąt zapytań zamiast ponad tysiąca","\u002Fart\u002Fblog\u002Fpokedex.svg",{"type":8,"value":9,"toc":157},"minimark",[10,14,17,22,25,28,41,53,57,75,78,85,89,92,107,110,114,117,128,132,146],[11,12,13],"p",{},"Pokedex to mój pierwszy większy projekt w JavaScripcie. Pisałem go równolegle z kursem – bez frameworka, na własnych klasach. Chciałem zrobić coś trudniejszego niż kolejną listę zadań i coś, czego nie znalazłem gotowego.",[11,15,16],{},"Pokemony wybrałem z prostego powodu: są od lat, więc ktoś na pewno zbudował już dla nich API. Tak było – PokéAPI wyskoczyło w wyszukiwarce jako pierwsze. Dane wprowadza ktoś inny, a ja mogłem skupić się na kodzie.",[18,19,21],"h2",{"id":20},"problem-dane-są-w-wielu-miejscach","Problem: dane są w wielu miejscach",[11,23,24],{},"W PokéAPI każdy pokemon ma swój adres z kompletem danych. Najprostsza droga to jedno zapytanie na pokemona – tak robi większość tutoriali z pierwszą generacją. Przy ponad 1000 gatunków to ponad 1000 zapytań przy każdym wejściu na stronę. Bałem się, że to zbyt mocno obciąży serwer, a strona będzie się długo ładować.",[11,26,27],{},"Dlatego odwróciłem kolejność. Zamiast pytać każdego pokemona o jego typ, pytam każdy typ o jego pokemony:",[29,30,31,35,38],"ol",{},[32,33,34],"li",{},"lista gatunków – jedno zapytanie daje numery i nazwy wszystkich pokemonów,",[32,36,37],{},"typy – każdy typ zwraca listę pokemonów, które go mają,",[32,39,40],{},"generacje – każda generacja zwraca listę swoich gatunków.",[11,42,43,44,48,49,52],{},"Zapytania o typy i generacje idą równolegle przez ",[45,46,47],"code",{},"Promise.all",". Do tego osobne zapytania o nazwy z myślnikiem – API zwraca np. ",[45,50,51],{},"mr-mime",", a na liście chciałem mieć „Mr. Mime”. W sumie wychodzi kilkadziesiąt zapytań zamiast ponad tysiąca.",[18,54,56],{"id":55},"mała-baza-w-przeglądarce","Mała baza w przeglądarce",[11,58,59,60,63,64,63,67,70,71,74],{},"Z tych odpowiedzi składam jeden obiekt: numer pokemona → nazwa, typy i generacja. Klucze są jednoliterowe (",[45,61,62],{},"n",", ",[45,65,66],{},"t",[45,68,69],{},"g","), bo całość trafia do ",[45,72,73],{},"localStorage",", a tam miejsce jest ograniczone.",[11,76,77],{},"Przy kolejnej wizycie strona pyta API tylko o to, ile jest teraz gatunków. Jeśli liczba zgadza się z tą w pamięci, lista ładuje się z przeglądarki – to dwa zapytania zamiast kilkudziesięciu. Jeśli w API pojawią się nowe pokemony, baza zbuduje się od nowa sama. Tego chciałem od początku: żeby raz napisany kod działał dalej beze mnie.",[11,79,80,81,84],{},"Wzrost, waga i statystyki pobieram dopiero wtedy, gdy ktoś otworzy kartę pokemona. Trafiają do ",[45,82,83],{},"sessionStorage",", więc drugie otwarcie tej samej karty nie wysyła już zapytania.",[18,86,88],{"id":87},"co-chwilę-nowy-pomysł","Co chwilę nowy pomysł",[11,90,91],{},"Sama lista szybko mi nie wystarczyła. W trakcie pisania co chwilę chciałem coś dodać:",[93,94,95,98,101,104],"ul",{},[32,96,97],{},"zaznaczanie złapanych pokemonów – lista zapisuje się w przeglądarce,",[32,99,100],{},"import i eksport tej listy, żeby przenieść ją na inne urządzenie albo do innej przeglądarki,",[32,102,103],{},"jasny i ciemny motyw,",[32,105,106],{},"paginację z numerem strony w adresie, żeby link prowadził od razu w to samo miejsce.",[11,108,109],{},"Pomysłów było więcej niż czasu. Często zaczynałem kolejną rzecz, zanim poprzednia działała do końca tak, jak powinna – i potem wracałem do kilku miejsc naraz.",[18,111,113],{"id":112},"błędy-które-uczyły-najwięcej","Błędy, które uczyły najwięcej",[11,115,116],{},"Na początku kilka razy wpadłem w pętlę, która przeciążała komputer. Potem przyszła asynchroniczność – musiałem sprawdzać, gdzie wysyłam zapytanie, co dostaję i czy te dane w ogóle są mi potrzebne. Najtrudniejsze okazało się zgranie tego z DOM-em: dane już są, a widok jeszcze nie, albo odwrotnie.",[11,118,119,120,123,124,127],{},"Moim głównym narzędziem był ",[45,121,122],{},"console.log"," i ",[45,125,126],{},"console.trace",". Dziś częściej zatrzymałbym kod w debuggerze w miejscu, gdzie coś się dzieje – wtedy tego nie robiłem, a pewnie zaoszczędziłbym sporo czasu.",[18,129,131],{"id":130},"co-zrobiłbym-dziś-inaczej","Co zrobiłbym dziś inaczej",[93,133,134,137,140,143],{},[32,135,136],{},"Kończyłbym jedną funkcję, zanim zacznę następną. Do pracy małymi krokami doszedłem dopiero po jakimś czasie.",[32,138,139],{},"Najpierw przeanalizowałbym, jak API podaje dane i czego naprawdę potrzebuję, a dopiero potem pisał kod.",[32,141,142],{},"Może najpierw zrobiłbym wygląd, a potem funkcje – wygląd zmieniałem wiele razy w trakcie.",[32,144,145],{},"Nie wszystko musi być klasą. Niektóre części dziś napisałbym jako zwykłe funkcje.",[11,147,148,149,156],{},"Projekt nie wygląda na wielki, ale dla mnie był ważnym krokiem. Kiedyś chcę przepisać go na Vue – temat ten sam, nowa lekcja. Na razie ",[150,151,155],"a",{"href":152,"rel":153},"https:\u002F\u002Flukaszdzielo.github.io\u002Fpokedex\u002F",[154],"nofollow","Pokedex działa tutaj",".",{"title":158,"searchDepth":159,"depth":159,"links":160},"",2,[161,162,163,164,165],{"id":20,"depth":159,"text":21},{"id":55,"depth":159,"text":56},{"id":87,"depth":159,"text":88},{"id":112,"depth":159,"text":113},{"id":130,"depth":159,"text":131},"2024-03-20","Jak w czystym JavaScripcie zbudowałem Pokedex na ponad 1000 pokemonów – z kolejnością pobierania danych z PokéAPI i małą bazą w przeglądarce.",false,"md",null,"post",{},true,"\u002Fog\u002Fblog\u002Fpokedex-pl.jpg","\u002Fpl\u002Fwpisy\u002F2024\u002Fpokedex-kilkadziesiat-zapytan-zamiast-tysiaca","\u002Fprojects\u002F2024\u002Fpokedex",{"title":5,"description":167},"pl\u002Fwpisy\u002F2024\u002Fpokedex-kilkadziesiat-zapytan-zamiast-tysiaca",[180,181,182],"javascript","pokeapi","projekt","pokedex-kilkadziesiat-zapytan-zamiast-tysiaca","j4ST6RX7Y1n__417v3iUezLoHp9O2aOHrJ04y5eNU4k",{"id":186,"title":187,"agency":170,"body":188,"compare":170,"cover":243,"date":249,"description":250,"draft":168,"extension":169,"facts":251,"featured":168,"gallery":265,"galleryLead":170,"highlights":170,"image":281,"links":282,"meta":284,"navigation":173,"note":170,"ogImage":285,"path":286,"seo":287,"stack":288,"stem":294,"tags":295,"__hash__":298},"projects_pl\u002Fpl\u002Fprojekty\u002F2024\u002Fpokedex\u002Findex.md","Pokedex",{"type":8,"value":189,"toc":240},[190,193,197],[11,191,192],{},"Pokedex to mój pierwszy większy projekt w JavaScripcie. Pisałem go równolegle z kursem i chciałem zrobić coś trudniejszego niż kolejną listę zadań. Wyszła interaktywna encyklopedia ponad 1000 pokemonów – w czystym JavaScripcie (ES6+, wzorce OOP), bez frameworków, na publicznym PokéAPI. W trakcie co chwilę wpadałem na nowe pomysły – złapane pokemony, eksport między przeglądarkami, motywy – i nie zawsze kończyłem jeden, zanim zacząłem następny. Dlatego zrobiłem listę i zacząłem wdrażać zmiany etapami – każdy nowy pomysł trafiał na listę „do zrobienia”, zamiast odciągać mnie od tego, co akurat robiłem.",[18,194,196],{"id":195},"najważniejsze-cechy","Najważniejsze cechy",[93,198,199,204,215,231,234,237],{},[32,200,201,202],{},"Przemyślana kolejność ładowania danych z PokéAPI – równoległe zapytania przez ",[45,203,47],{},[32,205,206,207,210,211,214],{},"Lokalna baza w przeglądarce (",[45,208,209],{},"LocalStorage"," + ",[45,212,213],{},"SessionStorage",") – raz pobrane dane nie idą drugi raz do API",[32,216,217,218,63,221,63,224,63,227,230],{},"Modułowa architektura klas (",[45,219,220],{},"DataManager",[45,222,223],{},"DataBuilder",[45,225,226],{},"StorageManager",[45,228,229],{},"PokemonDialog",") przygotowana pod migrację do Vue 3",[32,232,233],{},"Responsywna, dwukierunkowo synchronizowana paginacja z odwzorowaniem stanu w URL",[32,235,236],{},"Jasny i ciemny motyw (też automatyczny, według ustawień systemu)",[32,238,239],{},"Złapane pokemony – zaznaczanie w karcie pokemona, import i eksport listy w ustawieniach",{"title":158,"searchDepth":159,"depth":159,"links":241},[242],{"id":195,"depth":159,"text":196},{"desktop":244,"phone":245,"width":246,"height":247,"alt":248},"\u002Fprojects\u002F2024\u002Fpokedex\u002Flist.webp","\u002Fprojects\u002F2024\u002Fpokedex\u002Fphone.webp",1920,1105,"Pokedex – lista pokemonów z paginacją","2024-01-28","Interaktywny Pokedex na ponad 1000 pokemonów w czystym JavaScript (OOP), oparty o PokéAPI – z przemyślaną kolejnością ładowania danych i lokalną bazą w przeglądarce.",[252,255,258,262],{"value":253,"text":254},"2024","rok realizacji",{"value":256,"text":257},"Solo","projekt własny – od pomysłu po wdrożenie",{"value":259,"suffix":260,"text":261},"1000","+","pokemonów z PokéAPI – kilkadziesiąt zapytań zamiast ponad 1000",{"value":263,"text":264},"Vanilla JS","bez Vue, Reacta i innych frameworków – własne klasy w czystym JavaScript",[266,269,273,277],{"src":244,"width":246,"height":247,"alt":267,"caption":268},"Lista pokemonów z paginacją","Lista – ponad 1000 pokemonów, numer strony zapisany w adresie (?p=)",{"src":245,"device":270,"alt":271,"caption":272},"phone","Pokedex na telefonie – karta pokemona","Telefon – karta pokemona otwarta nad listą w dwóch kolumnach",{"src":274,"width":246,"height":247,"alt":275,"caption":276},"\u002Fprojects\u002F2024\u002Fpokedex\u002Fpokemon-card.webp","Okno szczegółów pokemona","Karta pokemona – nazwa, typy i generacja od razu z pamięci, statystyki dociągane z API",{"src":278,"width":246,"height":247,"alt":279,"caption":280},"\u002Fprojects\u002F2024\u002Fpokedex\u002Fsettings.webp","Ustawienia aplikacji","Ustawienia – motyw, import i eksport złapanych pokemonów, czyszczenie danych","\u002Fprojects\u002F2024\u002Fpokedex\u002Fthumbnail.webp",{"live":152,"github":283},"https:\u002F\u002Fgithub.com\u002Flukaszdzielo\u002Fpokedex",{},"\u002Fog\u002Fprojects\u002Fpokedex-pl.jpg","\u002Fpl\u002Fprojekty\u002F2024\u002Fpokedex",{"title":187,"description":250},[289,290,291,209,292,293],"JavaScript (ES6+)","OOP","PokéAPI","SCSS","bez frameworków","pl\u002Fprojekty\u002F2024\u002Fpokedex\u002Findex",[180,296,297,181],"vanilla-js","oop","aQJXRVAYAjI8gpEXDegmJbNVlSIlxLlKc_55AN8Pat8",1792530786540]