# בניית אפליקציית בנקאות חלק 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 (JavaScript ו-XML אסינכרוניים)](https://en.wikipedia.org/wiki/Ajax_(programming)). טכניקה זו מאפשרת לאפליקציות ווב לשלוח ולקבל נתונים משרת בצורה אסינכרונית באמצעות JavaScript, מבלי לטעון מחדש את דף ה-HTML, מה שמוביל לעדכונים מהירים יותר ואינטראקציות חלקות יותר. כאשר מתקבלים נתונים חדשים מהשרת, ניתן לעדכן את דף ה-HTML הנוכחי באמצעות JavaScript באמצעות [API של DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model). עם הזמן, גישה זו התפתחה למה שמכונה כיום [*אפליקציית דף יחיד* או *SPA*](https://en.wikipedia.org/wiki/Single-page_application).  כאשר AJAX הוצג לראשונה, ה-API היחיד שהיה זמין לשליפת נתונים אסינכרונית היה [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). אך דפדפנים מודרניים תומכים כיום גם ב-API הנוח והחזק יותר [`Fetch`](https://developer.mozilla.org/docs/Web/API/Fetch_API), המשתמש ב-promises ומתאים יותר לעבודה עם נתוני JSON. > למרות שכל הדפדפנים המודרניים תומכים ב-`Fetch API`, אם ברצונכם שאפליקציית הווב שלכם תפעל בדפדפנים ישנים, כדאי לבדוק תחילה את [טבלת התאימות ב-caniuse.com](https://caniuse.com/fetch). ### משימה בשיעור הקודם יישמנו את טופס ההרשמה ליצירת חשבון. כעת נוסיף קוד להתחברות באמצעות חשבון קיים ולשליפת נתוניו. פתחו את הקובץ `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; ``` לאחר שמירת נתוני המשתמש במשתנה, נוכל לנווט מדף *ההתחברות* לדף *לוח הבקרה* באמצעות הפונקציה `navigate()` שכבר יש לנו. לבסוף, עלינו לקרוא לפונקציית `login` שלנו כאשר טופס ההתחברות נשלח, על ידי שינוי ה-HTML: ```html