# Δημιουργία Εφαρμογής Τραπεζικής Διαχείρισης Μέρος 3: Μέθοδοι Ανάκτησης και Χρήσης Δεδομένων ## Ερωτηματολόγιο Πριν το Μάθημα [Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/45) ### Εισαγωγή Στον πυρήνα κάθε διαδικτυακής εφαρμογής βρίσκονται τα *δεδομένα*. Τα δεδομένα μπορούν να έχουν πολλές μορφές, αλλά ο κύριος σκοπός τους είναι πάντα να εμφανίζουν πληροφορίες στον χρήστη. Με τις διαδικτυακές εφαρμογές να γίνονται όλο και πιο διαδραστικές και πολύπλοκες, το πώς ο χρήστης αποκτά πρόσβαση και αλληλεπιδρά με τις πληροφορίες αποτελεί πλέον βασικό μέρος της ανάπτυξης ιστοσελίδων. Σε αυτό το μάθημα, θα δούμε πώς να ανακτούμε δεδομένα από έναν διακομιστή ασύγχρονα και να χρησιμοποιούμε αυτά τα δεδομένα για να εμφανίζουμε πληροφορίες σε μια ιστοσελίδα χωρίς να χρειάζεται να ανανεώνουμε το HTML. ### Προαπαιτούμενα Πρέπει να έχετε δημιουργήσει το [Φόρμα Εισόδου και Εγγραφής](../2-forms/README.md) μέρος της διαδικτυακής εφαρμογής για αυτό το μάθημα. Επίσης, πρέπει να έχετε εγκαταστήσει το [Node.js](https://nodejs.org) και να [εκτελέσετε το API του διακομιστή](../api/README.md) τοπικά ώστε να αποκτήσετε δεδομένα λογαριασμού. Μπορείτε να ελέγξετε αν ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX και ανάκτηση δεδομένων Οι παραδοσιακές ιστοσελίδες ενημερώνουν το περιεχόμενο που εμφανίζεται όταν ο χρήστης επιλέγει έναν σύνδεσμο ή υποβάλλει δεδομένα μέσω μιας φόρμας, ανανεώνοντας ολόκληρη τη σελίδα HTML. Κάθε φορά που χρειάζονται νέα δεδομένα, ο διακομιστής επιστρέφει μια ολοκαίνουργια σελίδα HTML που πρέπει να επεξεργαστεί ο περιηγητής, διακόπτοντας τη δράση του χρήστη και περιορίζοντας τις αλληλεπιδράσεις κατά τη διάρκεια της ανανέωσης. Αυτή η ροή εργασίας ονομάζεται επίσης *Εφαρμογή Πολλαπλών Σελίδων* ή *MPA*.  Όταν οι διαδικτυακές εφαρμογές άρχισαν να γίνονται πιο πολύπλοκες και διαδραστικές, εμφανίστηκε μια νέα τεχνική που ονομάζεται [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Αυτή η τεχνική επιτρέπει στις διαδικτυακές εφαρμογές να στέλνουν και να ανακτούν δεδομένα από έναν διακομιστή ασύγχρονα χρησιμοποιώντας JavaScript, χωρίς να χρειάζεται να ανανεώνεται η σελίδα HTML, με αποτέλεσμα ταχύτερες ενημερώσεις και ομαλότερες αλληλεπιδράσεις χρήστη. Όταν λαμβάνονται νέα δεδομένα από τον διακομιστή, η τρέχουσα σελίδα HTML μπορεί επίσης να ενημερωθεί με JavaScript χρησιμοποιώντας το [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) API. Με την πάροδο του χρόνου, αυτή η προσέγγιση εξελίχθηκε σε αυτό που τώρα ονομάζεται [*Εφαρμογή Μίας Σελίδας* ή *SPA*](https://en.wikipedia.org/wiki/Single-page_application).  Όταν το AJAX εισήχθη για πρώτη φορά, η μόνη διαθέσιμη API για ασύγχρονη ανάκτηση δεδομένων ήταν το [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Ωστόσο, οι σύγχρονοι περιηγητές υλοποιούν πλέον και την πιο βολική και ισχυρή [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), η οποία χρησιμοποιεί promises και είναι καλύτερα προσαρμοσμένη για τη διαχείριση δεδομένων JSON. > Παρόλο που όλοι οι σύγχρονοι περιηγητές υποστηρίζουν το `Fetch API`, αν θέλετε η διαδικτυακή σας εφαρμογή να λειτουργεί σε παλαιότερους περιηγητές, είναι πάντα καλή ιδέα να ελέγχετε πρώτα τον [πίνακα συμβατότητας στο caniuse.com](https://caniuse.com/fetch). ### Εργασία Στο [προηγούμενο μάθημα](../2-forms/README.md) υλοποιήσαμε τη φόρμα εγγραφής για τη δημιουργία λογαριασμού. Τώρα θα προσθέσουμε κώδικα για την είσοδο με έναν υπάρχοντα λογαριασμό και την ανάκτηση των δεδομένων του. Ανοίξτε το αρχείο `app.js` και προσθέστε μια νέα συνάρτηση `login`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Ξεκινάμε ανακτώντας το στοιχείο της φόρμας με τη μέθοδο `getElementById()`, και στη συνέχεια παίρνουμε το όνομα χρήστη από την είσοδο με `loginForm.user.value`. Κάθε στοιχείο φόρμας μπορεί να προσπελαστεί μέσω του ονόματός του (που ορίζεται στο HTML με το χαρακτηριστικό `name`) ως ιδιότητα της φόρμας. Με παρόμοιο τρόπο με αυτόν που χρησιμοποιήσαμε για την εγγραφή, θα δημιουργήσουμε μια άλλη συνάρτηση για να εκτελέσουμε ένα αίτημα στον διακομιστή, αλλά αυτή τη φορά για την ανάκτηση των δεδομένων του λογαριασμού: ```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' }; } } ``` Χρησιμοποιούμε το `fetch` API για να ζητήσουμε δεδομένα ασύγχρονα από τον διακομιστή, αλλά αυτή τη φορά δεν χρειαζόμαστε επιπλέον παραμέτρους πέρα από το URL που θα καλέσουμε, καθώς απλώς ζητάμε δεδομένα. Από προεπιλογή, το `fetch` δημιουργεί ένα HTTP αίτημα [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), το οποίο είναι αυτό που χρειαζόμαστε εδώ. ✅ Η `encodeURIComponent()` είναι μια συνάρτηση που διαφεύγει ειδικούς χαρακτήρες για URL. Τι προβλήματα θα μπορούσαμε να έχουμε αν δεν καλέσουμε αυτή τη συνάρτηση και χρησιμοποιήσουμε απευθείας την τιμή `user` στο URL; Ας ενημερώσουμε τώρα τη συνάρτηση `login` για να χρησιμοποιεί τη `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'); } ``` Αρχικά, επειδή η `getAccount` είναι μια ασύγχρονη συνάρτηση, πρέπει να τη συνδυάσουμε με τη λέξη-κλειδί `await` για να περιμένουμε το αποτέλεσμα του διακομιστή. Όπως με κάθε αίτημα στον διακομιστή, πρέπει επίσης να διαχειριστούμε περιπτώσεις σφαλμάτων. Προς το παρόν, θα προσθέσουμε μόνο ένα μήνυμα καταγραφής για να εμφανίσουμε το σφάλμα και θα επιστρέψουμε σε αυτό αργότερα. Στη συνέχεια, πρέπει να αποθηκεύσουμε τα δεδομένα κάπου ώστε να μπορούμε να τα χρησιμοποιήσουμε αργότερα για να εμφανίσουμε τις πληροφορίες του πίνακα ελέγχου. Επειδή η μεταβλητή `account` δεν υπάρχει ακόμα, θα δημιουργήσουμε μια καθολική μεταβλητή στην κορυφή του αρχείου μας: ```js let account = null; ``` Αφού αποθηκευτούν τα δεδομένα του χρήστη σε μια μεταβλητή, μπορούμε να μεταβούμε από τη σελίδα *login* στη σελίδα *dashboard* χρησιμοποιώντας τη συνάρτηση `navigate()` που έχουμε ήδη. Τέλος, πρέπει να καλέσουμε τη συνάρτηση `login` όταν υποβάλλεται η φόρμα εισόδου, τροποποιώντας το HTML: ```html