# Membina Aplikasi Perbankan Bahagian 3: Kaedah Mendapatkan dan Menggunakan Data Fikirkan tentang komputer Enterprise dalam Star Trek - apabila Kapten Picard meminta status kapal, maklumat muncul serta-merta tanpa keseluruhan antara muka terhenti dan dibina semula. Aliran maklumat yang lancar itulah yang kita bina di sini dengan pengambilan data secara dinamik. Sekarang, aplikasi perbankan anda seperti surat khabar bercetak - informatif tetapi statik. Kita akan mengubahnya menjadi sesuatu seperti pusat kawalan misi di NASA, di mana data mengalir secara berterusan dan dikemas kini secara masa nyata tanpa mengganggu aliran kerja pengguna. Anda akan belajar cara berkomunikasi dengan pelayan secara asinkron, mengendalikan data yang tiba pada masa yang berbeza, dan mengubah maklumat mentah menjadi sesuatu yang bermakna untuk pengguna anda. Inilah perbezaan antara demo dan perisian yang sedia untuk pengeluaran. ## Kuiz Pra-Kuliah [Kuiz pra-kuliah](https://ff-quizzes.netlify.app/web/quiz/45) ### Prasyarat Sebelum mendalami pengambilan data, pastikan anda mempunyai komponen berikut: - **Pelajaran Sebelumnya**: Lengkapkan [Borang Log Masuk dan Pendaftaran](../2-forms/README.md) - kita akan membina berdasarkan asas ini - **Pelayan Tempatan**: Pasang [Node.js](https://nodejs.org) dan [jalankan API pelayan](../api/README.md) untuk menyediakan data akaun - **Sambungan API**: Uji sambungan pelayan anda dengan arahan ini: ```bash curl http://localhost:5000/api # Expected response: "Bank API v1.0.0" ``` Ujian pantas ini memastikan semua komponen berkomunikasi dengan betul: - Mengesahkan bahawa Node.js berjalan dengan betul pada sistem anda - Mengesahkan pelayan API anda aktif dan memberi respons - Memastikan aplikasi anda dapat mencapai pelayan (seperti memeriksa hubungan radio sebelum misi) --- ## Memahami Pengambilan Data dalam Aplikasi Web Moden Cara aplikasi web mengendalikan data telah berkembang dengan ketara dalam dua dekad yang lalu. Memahami evolusi ini akan membantu anda menghargai mengapa teknik moden seperti AJAX dan Fetch API sangat berkuasa dan mengapa ia menjadi alat penting bagi pembangun web. Mari kita terokai bagaimana laman web tradisional berfungsi berbanding aplikasi dinamik dan responsif yang kita bina hari ini. ### Aplikasi Berbilang Halaman Tradisional (MPA) Pada zaman awal web, setiap klik seperti menukar saluran di televisyen lama - skrin akan menjadi kosong, kemudian perlahan-lahan menyesuaikan diri dengan kandungan baru. Inilah realiti aplikasi web awal, di mana setiap interaksi bermaksud membina semula keseluruhan halaman dari awal. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Clicks link or submits form Browser->>Server: Requests new HTML page Note over Browser: Page goes blank Server->>Browser: Returns complete HTML page Browser->>User: Displays new page (flash/reload) ``` ![Aliran kerja kemas kini dalam aplikasi berbilang halaman](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.ms.png) **Mengapa pendekatan ini terasa tidak lancar:** - Setiap klik bermaksud membina semula keseluruhan halaman dari awal - Pengguna terganggu di tengah-tengah pemikiran oleh kilatan halaman yang menjengkelkan - Sambungan internet anda bekerja keras memuat turun header dan footer yang sama berulang kali - Aplikasi terasa lebih seperti membuka fail dalam kabinet daripada menggunakan perisian ### Aplikasi Halaman Tunggal Moden (SPA) AJAX (Asynchronous JavaScript and XML) mengubah paradigma ini sepenuhnya. Seperti reka bentuk modular Stesen Angkasa Antarabangsa, di mana angkasawan boleh menggantikan komponen individu tanpa membina semula keseluruhan struktur, AJAX membolehkan kita mengemas kini bahagian tertentu halaman web tanpa memuat semula semuanya. Walaupun namanya menyebut XML, kita kebanyakannya menggunakan JSON hari ini, tetapi prinsip asasnya tetap sama: kemas kini hanya apa yang perlu diubah. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Interacts with page Browser->>JavaScript: Triggers event handler JavaScript->>Server: Fetches only needed data Server->>JavaScript: Returns JSON data JavaScript->>Browser: Updates specific page elements Browser->>User: Shows updated content (no reload) ``` ![Aliran kerja kemas kini dalam aplikasi halaman tunggal](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.ms.png) **Mengapa SPA terasa lebih baik:** - Hanya bahagian yang benar-benar berubah dikemas kini (bijak, bukan?) - Tiada gangguan yang mengejutkan - pengguna anda kekal dalam aliran mereka - Data yang lebih sedikit bergerak melalui rangkaian bermaksud pemuatan lebih pantas - Segalanya terasa pantas dan responsif, seperti aplikasi di telefon anda ### Evolusi kepada Fetch API Moden Pelayar moden menyediakan [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), yang menggantikan [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) yang lebih lama. Seperti perbezaan antara mengendalikan telegraf dan menggunakan e-mel, Fetch API menggunakan janji untuk kod asinkron yang lebih bersih dan mengendalikan JSON secara semula jadi. | Ciri | XMLHttpRequest | Fetch API | |------|----------------|-----------| | **Sintaks** | Berasaskan panggilan balik yang kompleks | Berasaskan janji yang bersih | | **Pengendalian JSON** | Perlu parsing manual | Kaedah `.json()` terbina dalam | | **Pengendalian Ralat** | Maklumat ralat terhad | Maklumat ralat yang komprehensif | | **Sokongan Moden** | Keserasian warisan | Janji ES6+ dan async/await | > 💡 **Keserasian Pelayar**: Berita baik - Fetch API berfungsi dalam semua pelayar moden! Jika anda ingin tahu tentang versi tertentu, [caniuse.com](https://caniuse.com/fetch) mempunyai cerita keserasian lengkap. > **Kesimpulannya:** - Berfungsi dengan baik dalam Chrome, Firefox, Safari, dan Edge (pada dasarnya di mana-mana pengguna anda berada) - Hanya Internet Explorer memerlukan bantuan tambahan (dan sejujurnya, sudah tiba masanya untuk melepaskan IE) - Menyediakan anda dengan sempurna untuk corak async/await yang elegan yang akan kita gunakan kemudian ### Melaksanakan Log Masuk Pengguna dan Pengambilan Data Sekarang mari kita laksanakan sistem log masuk yang mengubah aplikasi perbankan anda daripada paparan statik kepada aplikasi yang berfungsi. Seperti protokol pengesahan yang digunakan di kemudahan tentera yang selamat, kita akan mengesahkan kelayakan pengguna dan kemudian memberikan akses kepada data spesifik mereka. Kita akan membina ini secara berperingkat, bermula dengan pengesahan asas dan kemudian menambah keupayaan pengambilan data. #### Langkah 1: Buat Asas Fungsi Log Masuk Buka fail `app.js` anda dan tambahkan fungsi `login` baru. Ini akan mengendalikan proses pengesahan pengguna: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Mari kita pecahkan:** - Kata kunci `async` itu? Ia memberitahu JavaScript "hei, fungsi ini mungkin perlu menunggu sesuatu" - Kita mengambil borang kita dari halaman (tidak ada yang mewah, hanya mencarinya dengan ID) - Kemudian kita mengambil apa sahaja yang pengguna taip sebagai nama pengguna mereka - Ini adalah trik yang menarik: anda boleh mengakses mana-mana input borang dengan atribut `name` - tidak perlu panggilan getElementById tambahan! > 💡 **Corak Akses Borang**: Setiap kawalan borang boleh diakses dengan nama (ditetapkan dalam HTML menggunakan atribut `name`) sebagai sifat elemen borang. Ini menyediakan cara yang bersih dan mudah dibaca untuk mendapatkan data borang. #### Langkah 2: Buat Fungsi Pengambilan Data Akaun Seterusnya, kita akan membuat fungsi khusus untuk mendapatkan data akaun dari pelayan. Ini mengikuti corak yang sama seperti fungsi pendaftaran anda tetapi memberi tumpuan kepada pengambilan data: ```javascript 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' }; } } ``` **Inilah yang dicapai oleh kod ini:** - **Menggunakan** Fetch API moden untuk meminta data secara asinkron - **Membina** URL permintaan GET dengan parameter nama pengguna - **Menerapkan** `encodeURIComponent()` untuk mengendalikan watak khas dalam URL dengan selamat - **Menukar** respons kepada format JSON untuk manipulasi data yang mudah - **Mengendalikan** ralat dengan baik dengan mengembalikan objek ralat dan bukannya terhenti > ⚠️ **Nota Keselamatan**: Fungsi `encodeURIComponent()` mengendalikan watak khas dalam URL. Seperti sistem pengekodan yang digunakan dalam komunikasi tentera laut, ia memastikan mesej anda tiba dengan tepat seperti yang dimaksudkan, mencegah watak seperti "#" atau "&" daripada disalah tafsir. > **Mengapa ini penting:** - Mencegah watak khas daripada merosakkan URL - Melindungi daripada serangan manipulasi URL - Memastikan pelayan anda menerima data yang dimaksudkan - Mengikuti amalan pengekodan yang selamat #### Memahami Permintaan HTTP GET Berikut adalah sesuatu yang mungkin mengejutkan anda: apabila anda menggunakan `fetch` tanpa sebarang pilihan tambahan, ia secara automatik mencipta permintaan [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET). Ini sempurna untuk apa yang kita lakukan - meminta pelayan "hei, bolehkah saya melihat data akaun pengguna ini?" Fikirkan permintaan GET seperti meminta untuk meminjam buku dari perpustakaan dengan sopan - anda meminta untuk melihat sesuatu yang sudah ada. Permintaan POST (yang kita gunakan untuk pendaftaran) lebih seperti menyerahkan buku baru untuk ditambahkan ke koleksi. | Permintaan GET | Permintaan POST | |----------------|-----------------| | **Tujuan** | Mendapatkan data sedia ada | Menghantar data baru ke pelayan | | **Parameter** | Dalam laluan URL/string pertanyaan | Dalam badan permintaan | | **Caching** | Boleh dicache oleh pelayar | Tidak biasanya dicache | | **Keselamatan** | Terlihat dalam URL/log | Tersembunyi dalam badan permintaan | #### Langkah 3: Menggabungkan Semua Sekarang untuk bahagian yang memuaskan - mari kita sambungkan fungsi pengambilan akaun anda kepada proses log masuk. Di sinilah semuanya menjadi jelas: ```javascript 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'); } ``` Fungsi ini mengikuti urutan yang jelas: - Ekstrak nama pengguna dari input borang - Meminta data akaun pengguna dari pelayan - Mengendalikan sebarang ralat yang berlaku semasa proses - Menyimpan data akaun dan menavigasi ke papan pemuka setelah berjaya > 🎯 **Corak Async/Await**: Oleh kerana `getAccount` adalah fungsi asinkron, kita menggunakan kata kunci `await` untuk menghentikan pelaksanaan sehingga pelayan memberi respons. Ini menghalang kod daripada terus berjalan dengan data yang tidak ditentukan. #### Langkah 4: Mencipta Tempat untuk Data Anda Aplikasi anda memerlukan tempat untuk mengingati maklumat akaun setelah ia dimuatkan. Fikirkan ini seperti memori jangka pendek aplikasi anda - tempat untuk menyimpan data pengguna semasa. Tambahkan baris ini di bahagian atas fail `app.js` anda: ```javascript // This holds the current user's account data let account = null; ``` **Mengapa kita memerlukan ini:** - Menyimpan data akaun yang boleh diakses dari mana-mana dalam aplikasi anda - Bermula dengan `null` bermaksud "tiada siapa yang log masuk lagi" - Dikemas kini apabila seseorang berjaya log masuk atau mendaftar - Bertindak seperti sumber kebenaran tunggal - tiada kekeliruan tentang siapa yang log masuk #### Langkah 5: Sambungkan Borang Anda Sekarang mari kita sambungkan fungsi log masuk baru anda kepada borang HTML anda. Kemas kini tag borang anda seperti ini: ```html
``` **Apa yang dilakukan oleh perubahan kecil ini:** - Menghentikan borang daripada melakukan tingkah laku lalai "memuat semula keseluruhan halaman" - Memanggil fungsi JavaScript khusus anda sebagai gantinya - Menjaga semuanya lancar dan seperti aplikasi halaman tunggal - Memberikan anda kawalan penuh terhadap apa yang berlaku apabila pengguna menekan "Log Masuk" #### Langkah 6: Tingkatkan Fungsi Pendaftaran Anda Untuk konsistensi, kemas kini fungsi `register` anda untuk juga menyimpan data akaun dan menavigasi ke papan pemuka: ```javascript // Add these lines at the end of your register function account = result; navigate('/dashboard'); ``` **Peningkatan ini menyediakan:** - Peralihan **lancar** dari pendaftaran ke papan pemuka - Pengalaman pengguna **konsisten** antara aliran log masuk dan pendaftaran - Akses **segera** kepada data akaun selepas pendaftaran berjaya #### Uji Pelaksanaan Anda ```mermaid flowchart TD A[User enters credentials] --> B[Login function called] B --> C[Fetch account data from server] C --> D{Data received successfully?} D -->|Yes| E[Store account data globally] D -->|No| F[Display error message] E --> G[Navigate to dashboard] F --> H[User stays on login page] ``` **Masa untuk mencubanya:** 1. Buat akaun baru untuk memastikan semuanya berfungsi 2. Cuba log masuk dengan kelayakan yang sama 3. Lihat konsol pelayar anda (F12) jika ada yang tidak kena 4. Pastikan anda sampai ke papan pemuka selepas log masuk berjaya Jika ada yang tidak berfungsi, jangan panik! Kebanyakan masalah adalah pembetulan mudah seperti kesalahan ejaan atau terlupa untuk memulakan pelayan API. #### Sepatah Kata Tentang Keajaiban Cross-Origin Anda mungkin tertanya-tanya: "Bagaimana aplikasi web saya bercakap dengan pelayan API ini apabila mereka berjalan pada port yang berbeza?" Soalan yang bagus! Ini menyentuh sesuatu yang setiap pembangun web akan hadapi akhirnya. > 🔒 **Keselamatan Cross-Origin**: Pelayar menguatkuasakan "dasar asal yang sama" untuk mencegah komunikasi yang tidak sah antara domain yang berbeza. Seperti sistem pemeriksaan di Pentagon, mereka mengesahkan bahawa komunikasi dibenarkan sebelum membenarkan pemindahan data. > **Dalam tetapan kita:** - Aplikasi web anda berjalan di `localhost:3000` (pelayan pembangunan) - Pelayan API anda berjalan di `localhost:5000` (pelayan backend) - Pelayan API termasuk [header CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) yang secara eksplisit membenarkan komunikasi dari aplikasi web anda Konfigurasi ini mencerminkan pembangunan dunia nyata di mana aplikasi frontend dan backend biasanya berjalan di pelayan yang berasingan. > 📚 **Ketahui Lebih Lanjut**: Selami lebih mendalam tentang API dan pengambilan data dengan modul [Microsoft Learn tentang API](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Menghidupkan Data Anda dalam HTML Sekarang kita akan menjadikan data yang diambil kelihatan kepada pengguna melalui manipulasi DOM. Seperti proses membangunkan gambar dalam bilik gelap, kita mengambil data yang tidak kelihatan dan menjadikannya sesuatu yang boleh dilihat dan berinteraksi oleh pengguna. Manipulasi DOM adalah teknik yang mengubah halaman web statik menjadi aplikasi dinamik yang mengemas kini kandungannya berdasarkan interaksi pengguna dan respons pelayan. ### Memilih Alat yang Tepat untuk Tugas Apabila ia berkaitan dengan mengemas kini HTML anda dengan JavaScript, anda mempunyai beberapa pilihan. Fikirkan ini seperti alat yang berbeza dalam kotak alat - masing-masing sesuai untuk tugas tertentu: | Kaedah | Apa yang hebat untuk | Bila untuk menggunakannya | Tahap keselamatan | |--------|-----------------------|--------------------------|-------------------| | `textContent` | Memaparkan data pengguna dengan selamat | Bila-bila masa anda menunjukkan teks | ✅ Sangat selamat | | `createElement()` + `append()` | Membina susun atur yang kompleks | Membuat bahagian/senarai baru | ✅ Sangat selamat | | `innerHTML` | Menetapkan kandungan HTML | ⚠️ Cuba elakkan yang ini | ❌ Berisiko tinggi | #### Cara Selamat untuk Menunjukkan Teks: textContent Sifat [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) adalah sahabat terbaik anda apabila memaparkan data pengguna. Ia seperti mempunyai pengawal keselamatan untuk halaman web anda - tiada apa yang berbahaya dapat melalui: ```javascript // The safe, reliable way to update text const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **Kelebihan textContent:** - Menganggap segala-galanya sebagai teks biasa (menghalang pelaksanaan skrip) - Secara automatik membersihkan kandungan sedia ada - Cekap untuk kemas kini teks yang mudah - Memberikan keselamatan terbina dalam terhadap kandungan berbahaya #### Mencipta Elemen HTML Dinamik Untuk kandungan yang lebih kompleks, gabungkan [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) dengan kaedah [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append): ```javascript // Safe way to create new elements const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **Memahami pendekatan ini:** - **Mencipta** elemen DOM baru secara programatik - **Mengawal** sepenuhnya atribut dan kandungan elemen - **Membolehkan** struktur elemen yang kompleks dan bersarang - **Menjaga** keselamatan dengan memisahkan struktur daripada kandungan > ⚠️ **Pertimbangan Keselamatan**: Walaupun [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) sering muncul dalam tutorial, ia boleh melaksanakan skrip yang tertanam. Seperti protokol keselamatan di CERN yang menghalang pelaksanaan kod yang tidak sah, menggunakan `textContent` dan `createElement` adalah alternatif yang lebih selamat. > **Risiko innerHTML:** - Melaksanakan sebarang tag `