# Bina Aplikasi Perbankan Bahagian 3: Kaedah Mendapatkan dan Menggunakan Data ## Kuiz Pra-Kuliah [Kuiz pra-kuliah](https://ff-quizzes.netlify.app/web/quiz/45) ### Pengenalan Di teras setiap aplikasi web terdapat *data*. Data boleh wujud dalam pelbagai bentuk, tetapi tujuan utamanya adalah untuk memaparkan maklumat kepada pengguna. Dengan aplikasi web yang semakin interaktif dan kompleks, cara pengguna mengakses dan berinteraksi dengan maklumat kini menjadi bahagian penting dalam pembangunan web. Dalam pelajaran ini, kita akan melihat bagaimana mendapatkan data dari pelayan secara asinkron, dan menggunakan data ini untuk memaparkan maklumat pada halaman web tanpa memuat semula HTML. ### Prasyarat Anda perlu telah membina [Borang Log Masuk dan Pendaftaran](../2-forms/README.md) sebagai sebahagian daripada aplikasi web untuk pelajaran ini. Anda juga perlu memasang [Node.js](https://nodejs.org) dan [menjalankan API pelayan](../api/README.md) secara tempatan untuk mendapatkan data akaun. Anda boleh menguji sama ada pelayan berjalan dengan betul dengan melaksanakan perintah ini di terminal: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX dan pengambilan data Laman web tradisional mengemas kini kandungan yang dipaparkan apabila pengguna memilih pautan atau menghantar data menggunakan borang, dengan memuat semula keseluruhan halaman HTML. Setiap kali data baru perlu dimuatkan, pelayan web mengembalikan halaman HTML baru yang perlu diproses oleh pelayar, mengganggu tindakan pengguna semasa dan mengehadkan interaksi semasa pemuatan semula. Alur kerja ini juga dikenali sebagai *Aplikasi Berbilang Halaman* atau *MPA*.  Apabila aplikasi web mula menjadi lebih kompleks dan interaktif, teknik baru yang dipanggil [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)) muncul. Teknik ini membolehkan aplikasi web menghantar dan mendapatkan data dari pelayan secara asinkron menggunakan JavaScript, tanpa perlu memuat semula halaman HTML, menghasilkan kemas kini yang lebih pantas dan interaksi pengguna yang lebih lancar. Apabila data baru diterima dari pelayan, halaman HTML semasa juga boleh dikemas kini dengan JavaScript menggunakan API [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model). Lama kelamaan, pendekatan ini berkembang menjadi apa yang kini dipanggil [*Aplikasi Halaman Tunggal* atau *SPA*](https://en.wikipedia.org/wiki/Single-page_application).  Ketika AJAX pertama kali diperkenalkan, satu-satunya API yang tersedia untuk mendapatkan data secara asinkron adalah [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Tetapi pelayar moden kini juga melaksanakan API yang lebih mudah dan berkuasa, iaitu [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), yang menggunakan janji (promises) dan lebih sesuai untuk memanipulasi data JSON. > Walaupun semua pelayar moden menyokong `Fetch API`, jika anda mahu aplikasi web anda berfungsi pada pelayar lama atau warisan, adalah idea yang baik untuk memeriksa [jadual keserasian di caniuse.com](https://caniuse.com/fetch) terlebih dahulu. ### Tugasan Dalam [pelajaran sebelumnya](../2-forms/README.md) kita telah melaksanakan borang pendaftaran untuk mencipta akaun. Sekarang kita akan menambah kod untuk log masuk menggunakan akaun sedia ada, dan mendapatkan datanya. Buka fail `app.js` dan tambahkan fungsi `login` baru: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Di sini kita bermula dengan mendapatkan elemen borang menggunakan `getElementById()`, dan kemudian kita mendapatkan nama pengguna dari input dengan `loginForm.user.value`. Setiap kawalan borang boleh diakses melalui namanya (ditetapkan dalam HTML menggunakan atribut `name`) sebagai sifat borang. Dengan cara yang serupa seperti yang kita lakukan untuk pendaftaran, kita akan mencipta fungsi lain untuk melaksanakan permintaan pelayan, tetapi kali ini untuk mendapatkan data akaun: ```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' }; } } ``` Kita menggunakan `fetch` API untuk meminta data secara asinkron dari pelayan, tetapi kali ini kita tidak memerlukan parameter tambahan selain URL untuk dipanggil, kerana kita hanya membuat pertanyaan data. Secara lalai, `fetch` mencipta permintaan HTTP [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), yang merupakan apa yang kita perlukan di sini. ✅ `encodeURIComponent()` adalah fungsi yang melarikan watak khas untuk URL. Apakah masalah yang mungkin timbul jika kita tidak memanggil fungsi ini dan menggunakan nilai `user` secara langsung dalam URL? Sekarang mari kita kemas kini fungsi `login` kita untuk menggunakan `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'); } ``` Pertama, kerana `getAccount` adalah fungsi asinkron, kita perlu memadankannya dengan kata kunci `await` untuk menunggu hasil pelayan. Seperti mana-mana permintaan pelayan, kita juga perlu menangani kes ralat. Buat masa ini kita hanya akan menambah mesej log untuk memaparkan ralat, dan kembali kepadanya kemudian. Kemudian kita perlu menyimpan data di suatu tempat supaya kita boleh menggunakannya kemudian untuk memaparkan maklumat papan pemuka. Oleh kerana pembolehubah `account` belum wujud, kita akan mencipta pembolehubah global untuknya di bahagian atas fail kita: ```js let account = null; ``` Selepas data pengguna disimpan ke dalam pembolehubah, kita boleh menavigasi dari halaman *login* ke *dashboard* menggunakan fungsi `navigate()` yang telah kita ada. Akhir sekali, kita perlu memanggil fungsi `login` kita apabila borang log masuk dihantar, dengan mengubah suai HTML: ```html