# Jenga Programu ya Benki Sehemu ya 3: Mbinu za Kupata na Kutumia Data ## Jaribio la Kabla ya Somo [Jaribio la kabla ya somo](https://ff-quizzes.netlify.app/web/quiz/45) ### Utangulizi Katika msingi wa kila programu ya wavuti kuna *data*. Data inaweza kuwa katika aina nyingi, lakini lengo lake kuu daima ni kuonyesha taarifa kwa mtumiaji. Kwa kuwa programu za wavuti zinazidi kuwa shirikishi na ngumu, jinsi mtumiaji anavyopata na kuingiliana na taarifa sasa ni sehemu muhimu ya maendeleo ya wavuti. Katika somo hili, tutaona jinsi ya kupata data kutoka kwa seva kwa njia isiyo ya moja kwa moja, na kutumia data hiyo kuonyesha taarifa kwenye ukurasa wa wavuti bila kupakia upya HTML. ### Mahitaji ya Awali Unahitaji kuwa umejenga sehemu ya [Fomu ya Kuingia na Kusajili](../2-forms/README.md) ya programu ya wavuti kwa somo hili. Pia unahitaji kusakinisha [Node.js](https://nodejs.org) na [kuendesha API ya seva](../api/README.md) kwa ndani ili upate data ya akaunti. Unaweza kujaribu kama seva inafanya kazi vizuri kwa kutekeleza amri hii kwenye terminal: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX na Kupata Data Tovuti za jadi husasisha maudhui yanayoonyeshwa wakati mtumiaji anapochagua kiungo au kutuma data kwa kutumia fomu, kwa kupakia upya ukurasa mzima wa HTML. Kila wakati data mpya inahitajika kupakiwa, seva ya wavuti inarudisha ukurasa mpya wa HTML ambao unahitaji kuchakatwa na kivinjari, jambo linalokatiza hatua ya sasa ya mtumiaji na kupunguza mwingiliano wakati wa kupakia upya. Mtiririko huu pia huitwa *Programu ya Ukurasa Mbalimbali* au *MPA*.  Wakati programu za wavuti zilianza kuwa ngumu zaidi na shirikishi, mbinu mpya iliyoitwa [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)) ilianzishwa. Mbinu hii inaruhusu programu za wavuti kutuma na kupokea data kutoka kwa seva kwa njia isiyo ya moja kwa moja kwa kutumia JavaScript, bila kupakia upya ukurasa wa HTML, na hivyo kusababisha usasishaji wa haraka na mwingiliano laini wa mtumiaji. Wakati data mpya inapokelewa kutoka kwa seva, ukurasa wa sasa wa HTML unaweza pia kusasishwa kwa kutumia API ya [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model). Kwa muda, mbinu hii imebadilika na kuwa kile kinachoitwa sasa [*Programu ya Ukurasa Mmoja* au *SPA*](https://en.wikipedia.org/wiki/Single-page_application).  Wakati AJAX ilipoanzishwa kwa mara ya kwanza, API pekee iliyopatikana ya kupata data kwa njia isiyo ya moja kwa moja ilikuwa [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Lakini vivinjari vya kisasa sasa pia vinaunga mkono API rahisi na yenye nguvu zaidi [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), ambayo hutumia ahadi (promises) na inafaa zaidi kwa kuchakata data ya JSON. > Ingawa vivinjari vyote vya kisasa vinaunga mkono `Fetch API`, ikiwa unataka programu yako ya wavuti ifanye kazi kwenye vivinjari vya zamani, ni wazo zuri kila wakati kuangalia [jedwali la utangamano kwenye caniuse.com](https://caniuse.com/fetch) kwanza. ### Kazi Katika [somo lililopita](../2-forms/README.md) tulitekeleza fomu ya usajili ili kuunda akaunti. Sasa tutaongeza msimbo wa kuingia kwa kutumia akaunti iliyopo, na kupata data yake. Fungua faili `app.js` na ongeza kazi mpya `login`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Hapa tunaanza kwa kupata kipengele cha fomu kwa kutumia `getElementById()`, kisha tunapata jina la mtumiaji kutoka kwenye ingizo kwa `loginForm.user.value`. Kila kidhibiti cha fomu kinaweza kupatikana kwa jina lake (lililowekwa kwenye HTML kwa kutumia sifa ya `name`) kama mali ya fomu. Kwa njia sawa na tulivyofanya kwa usajili, tutaunda kazi nyingine ya kutekeleza ombi la seva, lakini wakati huu kwa kupata data ya akaunti: ```js async function getAccount(user) { try { const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user)); return await response.json(); } catch (error) { return { error: error.message || 'Unknown error' }; } } ``` Tunatumia `fetch` API kuomba data kwa njia isiyo ya moja kwa moja kutoka kwa seva, lakini wakati huu hatuhitaji vigezo vya ziada zaidi ya URL ya kupiga, kwa kuwa tunatafuta tu data. Kwa chaguo-msingi, `fetch` huunda ombi la HTTP la [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), ambalo ndilo tunalotafuta hapa. ✅ `encodeURIComponent()` ni kazi inayotoroka (escape) herufi maalum kwa URL. Ni matatizo gani yanaweza kutokea ikiwa hatutatumia kazi hii na kutumia moja kwa moja thamani ya `user` kwenye URL? Sasa wacha tusasishe kazi yetu ya `login` ili kutumia `getAccount`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; const data = await getAccount(user); if (data.error) { return console.log('loginError', data.error); } account = data; navigate('/dashboard'); } ``` Kwanza, kwa kuwa `getAccount` ni kazi isiyo ya moja kwa moja, tunahitaji kuifananisha na neno kuu `await` ili kusubiri matokeo ya seva. Kama ilivyo kwa ombi lolote la seva, pia tunapaswa kushughulikia kesi za makosa. Kwa sasa tutaongeza tu ujumbe wa logi kuonyesha kosa, na tutarudi kwenye hili baadaye. Kisha tunapaswa kuhifadhi data mahali fulani ili tuweze kuitumia baadaye kuonyesha taarifa za dashibodi. Kwa kuwa kigezo `account` bado hakipo, tutaumba kigezo cha kimataifa kwa ajili yake juu ya faili yetu: ```js let account = null; ``` Baada ya data ya mtumiaji kuhifadhiwa kwenye kigezo, tunaweza kuhamia kutoka ukurasa wa *login* hadi *dashboard* kwa kutumia kazi ya `navigate()` ambayo tayari tunayo. Hatimaye, tunahitaji kuita kazi yetu ya `login` wakati fomu ya kuingia inapotumwa, kwa kurekebisha HTML: ```html