# Δημιουργία Εφαρμογής Τραπεζικής Μέρος 3: Μέθοδοι Ανάκτησης και Χρήσης Δεδομένων ## Ερωτηματολόγιο Πριν το Μάθημα [Pre-lecture quiz](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