[{"data":1,"prerenderedAt":298},["ShallowReactive",2],{"blog-\u002Fblog\u002F2024\u002Fpokedex-a-few-dozen-requests-instead-of-a-thousand":3,"blog-project-\u002Fblog\u002F2024\u002Fpokedex-a-few-dozen-requests-instead-of-a-thousand":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_en\u002Fblog\u002F2024\u002Fpokedex-a-few-dozen-requests-instead-of-a-thousand.md","Pokedex – a few dozen requests instead of more than a thousand","\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 was my first bigger project in JavaScript. I wrote it while I was doing a course – no framework, just my own classes. I wanted to build something harder than another to-do list, and something I couldn't find ready-made.",[11,15,16],{},"I chose Pokémon for a simple reason: they have been around for years, so someone had surely built an API for them. I was right – PokéAPI was the first search result. Someone else keeps the data up to date, and I could focus on the code.",[18,19,21],"h2",{"id":20},"the-problem-the-data-is-in-many-places","The problem: the data is in many places",[11,23,24],{},"In PokéAPI every Pokémon has its own address with all its data. The easiest way is one request per Pokémon – that's what most tutorials do with the first generation. With more than 1,000 species, that means more than 1,000 requests every time someone opens the page. I was worried it would put too much load on the server and the page would load slowly.",[11,26,27],{},"So I turned it around. Instead of asking every Pokémon about its type, I ask every type about its Pokémon:",[29,30,31,35,38],"ol",{},[32,33,34],"li",{},"the species list – one request gives the numbers and names of all Pokémon,",[32,36,37],{},"types – each type returns the list of Pokémon that have it,",[32,39,40],{},"generations – each generation returns the list of its species.",[11,42,43,44,48,49,52],{},"The type and generation requests run in parallel with ",[45,46,47],"code",{},"Promise.all",". There are also separate requests for names with a hyphen – the API returns e.g. ",[45,50,51],{},"mr-mime",", and I wanted \"Mr. Mime\" on the list. In total, it's a few dozen requests instead of more than a thousand.",[18,54,56],{"id":55},"a-small-database-in-the-browser","A small database in the browser",[11,58,59,60,63,64,63,67,70,71,74],{},"From these responses I build one object: Pokémon number → name, types and generation. The keys are one letter long (",[45,61,62],{},"n",", ",[45,65,66],{},"t",[45,68,69],{},"g","), because everything goes to ",[45,72,73],{},"localStorage",", where space is limited.",[11,76,77],{},"On the next visit, the page only asks the API how many species there are now. If the number matches the one in memory, the list loads from the browser – that's two requests instead of a few dozen. If new Pokémon appear in the API, the database rebuilds itself. That was my goal from the start: code that keeps working without me.",[11,79,80,81,84],{},"Height, weight and stats are loaded only when someone opens a Pokémon card. They go to ",[45,82,83],{},"sessionStorage",", so opening the same card again doesn't send another request.",[18,86,88],{"id":87},"always-one-more-idea","Always one more idea",[11,90,91],{},"A simple list wasn't enough for long. While I was writing the code, I kept wanting to add something new:",[93,94,95,98,101,104],"ul",{},[32,96,97],{},"marking caught Pokémon – the list is saved in the browser,",[32,99,100],{},"import and export of that list, so you can move it to another device or browser,",[32,102,103],{},"a light and a dark theme,",[32,105,106],{},"pagination with the page number in the address, so a link opens the same page.",[11,108,109],{},"I had more ideas than time. I often started the next feature before the previous one worked the way it should – and then I had to go back to several places at once.",[18,111,113],{"id":112},"the-mistakes-that-taught-me-the-most","The mistakes that taught me the most",[11,115,116],{},"At the beginning I got stuck in a loop that overloaded my computer more than once. Then came async code – I had to check where I was sending a request, what I got back and whether I needed that data at all. The hardest part was keeping it in sync with the DOM: the data is ready but the view isn't, or the other way round.",[11,118,119,120,123,124,127],{},"My main tools were ",[45,121,122],{},"console.log"," and ",[45,125,126],{},"console.trace",". Today I would more often pause the code in the debugger at the point where something happens – I didn't do that back then, and it would probably have saved me a lot of time.",[18,129,131],{"id":130},"what-i-would-do-differently-today","What I would do differently today",[93,133,134,137,140,143],{},[32,135,136],{},"Finish one feature before starting the next. I learned to work in small steps only after some time.",[32,138,139],{},"First look at how the API returns data and what I really need, and only then write code.",[32,141,142],{},"Maybe build the look first and the features later – I changed the design many times along the way.",[32,144,145],{},"Not everything has to be a class. Today I would write some parts as plain functions.",[11,147,148,149,156],{},"The project doesn't look big, but it was an important step for me. One day I want to rewrite it in Vue – same topic, new lesson. For now, ",[150,151,155],"a",{"href":152,"rel":153},"https:\u002F\u002Flukaszdzielo.github.io\u002Fpokedex\u002F",[154],"nofollow","Pokedex is live here",".",{"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","How I built a Pokedex for more than 1,000 Pokémon in plain JavaScript – with a planned order of PokéAPI requests and a small database in the browser.",false,"md",null,"post",{},true,"\u002Fog\u002Fblog\u002Fpokedex-en.jpg","\u002Fblog\u002F2024\u002Fpokedex-a-few-dozen-requests-instead-of-a-thousand","\u002Fprojects\u002F2024\u002Fpokedex",{"title":5,"description":167},"blog\u002F2024\u002Fpokedex-a-few-dozen-requests-instead-of-a-thousand",[180,181,182],"javascript","pokeapi","project","pokedex-kilkadziesiat-zapytan-zamiast-tysiaca","HXtns2vOLf_b_n_Fj8N2SI1fMbOaJgqqF-w3IvPfomc",{"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":176,"seo":286,"stack":287,"stem":293,"tags":294,"__hash__":297},"projects_en\u002Fprojects\u002F2024\u002Fpokedex\u002Findex.md","Pokedex",{"type":8,"value":189,"toc":240},[190,193,197],[11,191,192],{},"Pokedex was my first bigger project in JavaScript. I wrote it alongside a course and wanted to build something harder than another to-do list. The result is an interactive encyclopedia of more than 1,000 Pokémon – in vanilla JavaScript (ES6+, OOP patterns), with no frameworks, using the public PokéAPI. While working on it, I kept getting new ideas – caught Pokémon, export between browsers, themes – and I didn't always finish one before starting the next. So I made a list and started adding changes in stages – every new idea went to a to-do list instead of pulling me away from what I was working on.",[18,194,196],{"id":195},"key-features","Key features",[93,198,199,204,215,231,234,237],{},[32,200,201,202],{},"A planned loading order for PokéAPI data – parallel requests with ",[45,203,47],{},[32,205,206,207,210,211,214],{},"A local database in the browser (",[45,208,209],{},"LocalStorage"," + ",[45,212,213],{},"SessionStorage",") – data is fetched from the API only once",[32,216,217,218,63,221,63,224,63,227,230],{},"A modular class architecture (",[45,219,220],{},"DataManager",[45,222,223],{},"DataBuilder",[45,225,226],{},"StorageManager",[45,228,229],{},"PokemonDialog",") ready for a migration to Vue 3",[32,232,233],{},"Responsive pagination synced in both directions, with its state reflected in the URL",[32,235,236],{},"Light and dark theme (also automatic, following the system setting)",[32,238,239],{},"Caught Pokémon – you can mark them in the Pokémon card, and import or export the list in the settings",{"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 – the Pokémon list with pagination","2024-01-28","An interactive Pokedex covering more than 1,000 Pokémon, written in vanilla JavaScript (OOP) on top of PokéAPI – with a planned data loading order and a local database in the browser.",[252,255,258,262],{"value":253,"text":254},"2024","year built",{"value":256,"text":257},"Solo","a personal project – from the idea to the release",{"value":259,"suffix":260,"text":261},"1000","+","Pokémon from PokéAPI – a few dozen requests instead of more than 1,000",{"value":263,"text":264},"Vanilla JS","no Vue, React or other frameworks – my own classes in plain JavaScript",[266,269,273,277],{"src":244,"width":246,"height":247,"alt":267,"caption":268},"The Pokémon list with pagination","The list – more than 1,000 Pokémon, with the page number saved in the URL (?p=)",{"src":245,"device":270,"alt":271,"caption":272},"phone","Pokedex on a phone – a Pokémon card","Phone – a Pokémon card open over the two-column list",{"src":274,"width":246,"height":247,"alt":275,"caption":276},"\u002Fprojects\u002F2024\u002Fpokedex\u002Fpokemon-card.webp","The Pokémon details window","Pokémon card – name, types and generation come straight from memory, stats are loaded from the API",{"src":278,"width":246,"height":247,"alt":279,"caption":280},"\u002Fprojects\u002F2024\u002Fpokedex\u002Fsettings.webp","App settings","Settings – theme, import and export of caught Pokémon, clearing the data","\u002Fprojects\u002F2024\u002Fpokedex\u002Fthumbnail.webp",{"live":152,"github":283},"https:\u002F\u002Fgithub.com\u002Flukaszdzielo\u002Fpokedex",{},"\u002Fog\u002Fprojects\u002Fpokedex-en.jpg",{"title":187,"description":250},[288,289,290,209,291,292],"JavaScript (ES6+)","OOP","PokéAPI","SCSS","no frameworks","projects\u002F2024\u002Fpokedex\u002Findex",[180,295,296,181],"vanilla-js","oop","n73SvaqKJSVyp4ayXCZzBpYSbh1YPmlM6zQZidCHcK0",1792530552515]