# ساخت اپ بانکداری بخش ۳: روشهای واکشی و استفاده از دادهها به کامپیوتر سفینه انتپرایز در استار ترک فکر کنید - وقتی کاپیتان پیکارد وضعیت سفینه را میپرسد، اطلاعات فوراً ظاهر میشوند بدون اینکه کل رابط کاربری خاموش شود و خود را از نو بسازد. آن جریان بیوقفه اطلاعات دقیقاً همان چیزی است که ما اینجا با واکشی دادههای پویا میسازیم. در حال حاضر، اپ بانکداری شما مثل یک روزنامه چاپی است - اطلاعرسان اما ایستا. ما میخواهیم آن را به چیزی شبیه مرکز عملیات ناسا تبدیل کنیم، جایی که دادهها بهصورت پیوسته جریان دارند و بهروزرسانیهای آنی را بدون قطع کردن جریان کاری کاربر ارائه میدهند. شما یاد میگیرید چطور بهصورت ناهمزمان با سرورها ارتباط برقرار کنید، دادههایی که در زمانهای مختلف میرسند را مدیریت کنید و اطلاعات خام را به چیزی معنادار برای کاربران خود تبدیل کنید. این تفاوت بین یک دمو و نرمافزار آماده تولید است. ## ⚡ آنچه میتوانید در ۵ دقیقه آینده انجام دهید **مسیر شروع سریع برای توسعهدهندگان پرمشغله** ```mermaid flowchart LR A[⚡ ۵ دقیقه] --> B[راهاندازی سرور API] B --> C[آزمایش واکشی با curl] C --> D[ساخت تابع ورود] D --> E[مشاهده دادهها در عمل] ``` - **دقیقه ۱-۲**: سرور API را اجرا کنید (`cd api && npm start`) و اتصال را آزمایش کنید - **دقیقه ۳**: یک تابع ساده `getAccount()` با استفاده از fetch بسازید - **دقیقه ۴**: فرم ورود را با `action="javascript:login()"` متصل کنید - **دقیقه ۵**: ورود را تست کنید و مشاهده کنید دادههای حساب در کنسول ظاهر میشوند **فرامین تست سریع**: ```bash # بررسی فعال بودن API curl http://localhost:5000/api # تست واکشی دادههای حساب کاربری curl http://localhost:5000/api/accounts/test ``` **چرا این مهم است**: در ۵ دقیقه، شما جادوی واکشی ناهمزمان داده را خواهید دید که نیروی محرکه هر برنامه وب مدرن است. این پایهای است که باعث میشود اپها پاسخگو و زنده به نظر برسند. ## 🗺️ مسیر یادگیری شما در برنامههای وب مبتنی بر داده ```mermaid journey title از صفحات استاتیک تا برنامههای داینامیک section درک تکامل بارگذاری مجدد صفحات سنتی: 3: You کشف مزایای AJAX/SPA: 5: You تسلط بر الگوهای Fetch API: 7: You section ساخت احراز هویت ایجاد توابع ورود: 4: You مدیریت عملیات ناهمزمان: 6: You مدیریت جلسات کاربری: 8: You section بهروزرسانیهای رابط کاربری داینامیک یادگیری دستکاری DOM: 5: You ساخت نمایش تراکنشها: 7: You ایجاد داشبوردهای پاسخگو: 9: You section الگوهای حرفهای رندر مبتنی بر قالب: 6: You استراتژیهای مدیریت خطا: 7: You بهینهسازی عملکرد: 8: You ``` **مقصد مسیر شما**: تا پایان این درس، شما میفهمید چطور برنامههای وب مدرن به صورت پویا دادهها را واکشی، پردازش و نمایش میدهند و تجربههای کاربری یکپارچهای که از برنامههای حرفهای انتظار داریم را خلق میکنند. ## آزمون قبل از درس [آزمون قبل از درس](https://ff-quizzes.netlify.app/web/quiz/45) ### پیشنیازها قبل از شروع واکشی داده، مطمئن شوید که این موارد آماده هستند: - **درس قبلی**: فرم [ورود و ثبتنام](../2-forms/README.md) را کامل کنید - ما بر این پایه خواهیم ساخت - **سرور محلی**: [Node.js](https://nodejs.org) را نصب کرده و [سرور API](../api/README.md) را اجرا کنید تا داده حسابها را فراهم کند - **ارتباط با API**: اتصال سرور خود را با این دستور تست کنید: ```bash curl http://localhost:5000/api # پاسخ مورد انتظار: "بانک API نسخه 1.0.0" ``` این تست سریع تضمین میکند همه اجزا به درستی با هم ارتباط دارند: - تایید میکند Node.js بهدرستی روی سیستم شما اجرا میشود - اطمینان میدهد سرور API فعال و پاسخگو است - اعتبارسنجی میکند که اپ شما میتواند به سرور دسترسی داشته باشد (مثل بررسی تماس رادیویی پیش از ماموریت) ## 🧠 مرور اکوسیستم مدیریت دادهها ```mermaid mindmap root((مدیریت دادهها)) Authentication Flow Login Process Form Validation Credential Verification Session Management User State Global Account Object Navigation Guards Error Handling API Communication Fetch Patterns GET Requests POST Requests Error Responses Data Formats JSON Processing URL Encoding Response Parsing Dynamic UI Updates DOM Manipulation Safe Text Updates Element Creation Template Cloning User Experience Real-time Updates Error Messages Loading States Security Considerations XSS Prevention textContent Usage Input Sanitization Safe HTML Creation CORS Handling Cross-Origin Requests Header Configuration Development Setup ``` **اصل اساسی**: برنامههای وب مدرن سیستمهای هماهنگکننده دادهاند — آنها بین رابطهای کاربری، APIهای سرور و مدلهای امنیتی مرورگر هماهنگی ایجاد میکنند تا تجربههای پاسخگو و یکپارچه خلق کنند. --- ## درک واکشی داده در برنامههای وب مدرن نحوه مدیریت داده در برنامههای وب طی دو دهه گذشته به شدت تغییر کرده است. درک این تحول به شما کمک میکند بیشتر قدر قدرت روشهای نوین مثل AJAX و Fetch API را بدانید و بفهمید چرا اینها به ابزارهای ضروری توسعهدهندگان وب تبدیل شدهاند. بیایید ببینیم وبسایتهای سنتی چگونه کار میکردند و آنها را با برنامههای پویا و پاسخگوی امروز مقایسه کنیم. ### برنامههای چندصفحهای سنتی (MPA) در روزهای ابتدایی وب، هر کلیک مثل عوض کردن کانال در یک تلویزیون قدیمی بود — صفحه خاموش میشد، بعد آهسته محتوا بارگذاری میشد. این واقعیت برنامههای وب اولیه بود، جایی که هر تعامل به معنی ساختن دوباره کل صفحه از اول بود. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: کلیک روی لینک یا ارسال فرم Browser->>Server: درخواست صفحه HTML جدید Note over Browser: صفحه خالی میشود Server->>Browser: ارسال صفحه کامل HTML Browser->>User: نمایش صفحه جدید (فلش/بارگذاری مجدد) ```  **چرا این روش کند و زمخت به نظر میرسید:** - هر کلیک به معنای ساختن کل صفحه از نو بود - کاربران وسط کارشان با آن فلشهای صفحه اذیت میشدند - اتصال اینترنت شما بار اضافی داشت چون مدام هدر و فوتر تکراری دانلود میشد - اپها بیشتر شبیه ورق زدن یک کشوی اسناد بودند تا استفاده از نرمافزار ### برنامههای تکصفحهای مدرن (SPA) AJAX (جاوااسکریپت ناهمزمان و XML) این پارادایم را کاملاً تغییر داد. مثل طراحی مدولار ایستگاه فضایی بینالمللی، جایی که فضانوردان میتوانند قطعات را بدون بازسازی کل سازه جایگزین کنند، AJAX اجازه میدهد بخشهای خاصی از صفحه وب را بدون بارگذاری مجدد کل صفحه بهروزرسانی کنیم. علیرغم نام آن که XML را میگوید، امروز بیشتر JSON استفاده میکنیم اما اصل اساسی این است: فقط بخشهای لازم بهروزرسانی میشوند. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: تعامل با صفحه Browser->>JavaScript: فعالسازی هندلر رویداد JavaScript->>Server: دریافت فقط دادههای موردنیاز Server->>JavaScript: بازگرداندن دادههای JSON JavaScript->>Browser: بهروزرسانی عناصر خاص صفحه Browser->>User: نمایش محتوای بهروزشده (بدون بارگذاری مجدد) ```  **چرا SPAها اینقدر بهتر به نظر میرسند:** - فقط بخشهایی که واقعاً تغییر کردهاند بهروزرسانی میشوند (هوشمندانه، درست است؟) - دیگر وقفههای ناگهانی وجود ندارد - کاربران در جریان خود باقی میمانند - حجم کمتری از دادهها روی شبکه منتقل میشود، یعنی بارگذاری سریعتر - همه چیز پاسخگو و چابک به نظر میرسد، مثل اپهای روی گوشی شما ### تحول به Fetch API مدرن مرورگرهای مدرن [`Fetch API`](https://developer.mozilla.org/docs/Web/API/Fetch_API) را ارائه میدهند که جایگزین قدیمیتر [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) شده است. مثل تفاوت بین استفاده از تلگراف و ایمیل، Fetch API از پرامیسها برای کد ناهمزمان تمیزتر استفاده میکند و JSON را به طور طبیعی هندل میکند. | ویژگی | XMLHttpRequest | Fetch API | |---------|----------------|----------| | **نحو** | callback-based پیچیده | promise-based تمیز | | **هندلینگ JSON** | نیاز به پارس دستی | متد داخلی `.json()` | | **مدیریت خطا** | اطلاعات خطای محدود | جزئیات خطا جامع | | **پشتیبانی مدرن** | سازگار با کدهای قدیمی | پرامیسها و async/await در ES6+ | > 💡 **سازگاری مرورگر**: خبر خوب این است که Fetch API در همه مرورگرهای مدرن کار میکند! اگر درباره نسخههای خاص کنجکاوید، [caniuse.com](https://caniuse.com/fetch) داستان کامل سازگاری را دارد. > **خلاصه:** - در کروم، فایرفاکس، سافاری و اج عالی است (عملاً در همه جا که کاربران شما هستند) - فقط اینترنت اکسپلورر نیاز به کمک اضافی دارد (و واقعاً وقتش است که از IE خداحافظی کنیم) - شما را کاملاً برای الگوهای async/await ظریف که بعداً استفاده میکنیم آماده میکند ### پیادهسازی ورود کاربر و واکشی دادهها حالا بیایید سیستم ورود را پیاده کنیم که اپ بانکداری شما را از نمایش ایستا به یک برنامه کاربردی واقعی تبدیل میکند. مثل پروتکلهای احراز هویت در مراکز نظامی امن، ما اعتبارسنجی کاربر را انجام میدهیم و سپس دسترسی به دادههای خاص او را فراهم میکنیم. این کار را به تدریج انجام میدهیم، ابتدا با احراز هویت پایه و سپس افزودن قابلیتهای واکشی داده. #### مرحله ۱: ایجاد پایه تابع ورود فایل `app.js` خود را باز کرده و یک تابع `login` جدید اضافه کنید. این تابع فرایند احراز هویت کاربر را مدیریت میکند: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **بیایید آن را تحلیل کنیم:** - آن کلیدواژه `async`؟ به جاوااسکریپت میگوید «هی، ممکن است این تابع نیاز داشته باشد منتظر چیزها بماند» - فرم را از صفحه میگیریم (چیز خاصی نیست، فقط بر اساس آیدی پیدا میشود) - سپس نام کاربری که کاربر وارد کرده را استخراج میکنیم - یک نکته جالب: میتوانید به هر ورودی فرم به وسیله صفت `name` آن دسترسی داشته باشید - نیازی به فراخوانی getElementById اضافی نیست! > 💡 **الگوی دسترسی به فرم**: هر کنترل فرم را میتوان با نام آن (تنظیم شده در HTML با صفت `name`) به عنوان یک ویژگی از عنصر فرم دسترسی داد. این روش خوانا و تمیزی برای گرفتن دادههای فرم فراهم میکند. #### مرحله ۲: ایجاد تابع واکشی داده حساب حالا تابعی مجزا برای واکشی داده حساب از سرور ایجاد میکنیم. این الگو مشابه تابع ثبتنام شما است ولی تمرکزش روی واکشی داده است: ```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' }; } } ``` **این کد چه کار میکند:** - **از** API مدرن `fetch` برای درخواست داده به صورت ناهمزمان استفاده میکند - **یک** URL درخواست GET با پارامتر نام کاربری میسازد - **از** `encodeURIComponent()` برای هندل امن کاراکترهای خاص در آدرسها استفاده میکند - **پاسخ را به** فرمت JSON برای پردازش آسان تبدیل میکند - **خطاها را بهطور مناسب هندل میکند** و به جای کرش دادن، یک شیء خطا بازمیگرداند > ⚠️ **نکته امنیتی**: تابع `encodeURIComponent()` کاراکترهای خاص در URL را هندل میکند. مثل سیستمهای رمزگذاری ارتباطی نیروی دریایی، تضمین میکند پیام شما دقیقاً همانطور که باید برسد و کاراکترهای مثل "#" یا "&" اشتباه تفسیر نشوند. > **چرا این مهم است:** - جلوگیری از خراب شدن آدرسهای اینترنتی با کاراکترهای خاص - محافظت در برابر حملات دستکاری URL - اطمینان از اینکه سرور داده صحیح را دریافت میکند - تبعیت از شیوههای برنامهنویسی امن #### درک درخواستهای HTTP GET شاید تعجب کنید: وقتی `fetch` را بدون هیچ گزینه اضافی استفاده میکنید، بهصورت خودکار یک درخواست [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) ارسال میکند. این برای کاری که ما انجام میدهیم عالی است — پرسیدن از سرور «هی، میتوانم داده حساب این کاربر را ببینم؟» درخواستهای GET مثل درخواست مودبانه قرض گرفتن یک کتاب از کتابخانه است — شما در حال درخواست دیدن چیزی هستید که قبلاً وجود دارد. درخواستهای POST (که برای ثبتنام استفاده کردیم) بیشتر شبیه ارسال کتاب جدید برای اضافه شدن به مجموعهاند. | درخواست GET | درخواست POST | |-------------|-------------| | **هدف** | واکشی داده موجود | ارسال داده جدید به سرور | | **پارامترها** | در مسیر/رشته پرس و جو URL | در بدنه درخواست | | **کش شدن** | قابل کش توسط مرورگرها | معمولاً کش نمیشود | | **امنیت** | قابل مشاهده در URL و لاگها | مخفی در بدنه درخواست | ```mermaid sequenceDiagram participant B as مرورگر participant S as سرور Note over B,S: درخواست GET (بازیابی داده) B->>S: GET /api/accounts/test S-->>B: 200 OK + داده حساب Note over B,S: درخواست POST (ارسال داده) B->>S: POST /api/accounts + داده حساب جدید S-->>B: 201 Created + تاییدیه Note over B,S: مدیریت خطا B->>S: GET /api/accounts/nonexistent S-->>B: 404 Not Found + پیام خطا ``` #### مرحله ۳: جمعبندی همه چیز حالا قسمت رضایتبخش است — تابع واکشی حساب شما را به فرایند ورود وصل میکنیم. جایی که همه چیز به هم میرسد: ```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'); } ``` این تابع دنباله روشنی دارد: - نام کاربری را از ورودی فرم استخراج میکند - اطلاعات حساب کاربر را از سرور درخواست میکند - هر خطایی که رخ میدهد را هندل میکند - داده حساب را ذخیره کرده و پس از موفقیت به داشبورد هدایت میکند > 🎯 **الگوی Async/Await**: چون `getAccount` یک تابع ناهمزمان است، ما از کلیدواژه `await` استفاده میکنیم تا اجرا تا زمان دریافت پاسخ سرور متوقف شود. این از ادامه کد با دادههای تعریف نشده جلوگیری میکند. #### مرحله ۴: ایجاد مکانی برای دادهها اپ شما نیاز دارد جایی اطلاعات حساب را پس از بارگذاری نگه دارد. این مثل حافظه کوتاهمدت اپ شماست — جایی برای در دسترس داشتن دادههای کاربر حاضر. این خط را در بالای فایل `app.js` خود اضافه کنید: ```javascript // این دادههای حساب کاربری فعلی را نگه میدارد let account = null; ``` **چرا این لازم است:** - دادههای حساب را در دسترس هر قسمتی از اپ نگه میدارد - شروع با مقدار `null` به معنی «فعلاً هیچکس وارد نشده» است - هنگام موفقیت در ورود یا ثبتنام بهروزرسانی میشود - مثل یک منبع یگانه حقیقت عمل میکند — هیچ سردرگمی درباره اینکه چه کسی وارد شده نیست #### مرحله ۵: اتصال فرم حالا بیایید تابع ورود جدید خود را به فرم HTML متصل کنیم. تگ فرم خود را اینگونه بهروزرسانی کنید: ```html
``` **این تغییر کوچک چه کاری انجام میدهد:** - جلوی رفتار پیشفرض فرم که صفحه را کامل بارگذاری مجدد میکند میگیرد - تابع جاوااسکریپت سفارشی شما را صدا میزند - همه چیز به صورت نرم و شبیه SPA باقی میماند - کنترل کامل خود را روی اتفاقات زمانی که کاربر روی «ورود» کلیک میکند به شما میدهد #### مرحله ۶: بهبود تابع ثبتنام برای سازگاری، تابع `register` خود را هم بهروزرسانی کنید تا داده حساب را ذخیره و به داشبورد هدایت کند: ```javascript // این خطوط را در انتهای تابع ثبت خود اضافه کنید account = result; navigate('/dashboard'); ``` **این بهبودها فراهم میکند:** - **تغییر روان** از ثبتنام به داشبورد - **تجربه کاربری هماهنگ** بین جریان ورود و ثبتنام - **دسترسی فوری** به داده حساب پس موفقیت ثبتنام #### آزمایش پیادهسازی ```mermaid flowchart TD A[کاربر اطلاعات ورود را وارد میکند] --> B[تابع ورود فراخوانی میشود] B --> C[دادههای حساب از سرور دریافت میشود] C --> D{آیا داده با موفقیت دریافت شد؟} D -->|بله| E[ذخیرهسازی دادههای حساب به صورت سراسری] D -->|خیر| F[نمایش پیام خطا] E --> G[هدایت به داشبورد] F --> H[کاربر در صفحه ورود باقی میماند] ``` **وقت آن است که امتحانش کنید:** 1. ابتدا یک حساب جدید بسازید تا همه چیز کار کند 2. با همان مشخصات وارد شوید 3. در صورت مشکل به کنسول مرورگر (F12) نگاه کنید 4. تأیید کنید پس از ورود موفق به داشبورد منتقل میشوید اگر چیزی کار نکرد نگران نباشید! اغلب مشکلات رفع ساده مانند اشتباهات تایپی یا فراموش کردن اجرای سرور API هستند. #### کلمهای کوتاه درباره جادوی Cross-Origin ممکن است بپرسید: «چطور اپ وب من با سرور API که روی پورتهای متفاوت اجرا میشوند ارتباط برقرار میکند؟» سؤال خوبی است! این موضوع به چیزی برمیگردد که هر توسعهدهنده وب بالاخره با آن مواجه میشود. > 🔒 **امنیت Cross-Origin**: مرورگرها سیاست «هممبدأی» را اجرا میکنند تا ارتباط غیرمجاز بین دامنههای مختلف را جلوگیری کنند. درست مثل سیستم ایست بازرسی در پنتاگون، آنها تأیید میکنند که ارتباط مجاز است قبل از اینکه اجازه انتقال داده بدهند. > **در تنظیمات ما:** - اپ وب روی `localhost:3000` اجرا میشود (سرور توسعه) - سرور API روی `localhost:5000` اجرا میشود (سرور بکاند) - سرور API شامل [هدرهای CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) است که صراحتاً اجازه ارتباط از اپ وب شما را میدهد این پیکربندی مثل موارد واقعی توسعه است که برنامههای فرانتاند و بکاند معمولاً روی سرورهای جداگانه اجرا میشوند. > 📚 **بیشتر بیاموزید**: با این [ماژول مایکروسافت در مورد APIs](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon) به عمق موضوع کار با API و واکشی داده بروید. ## زنده کردن دادهها در HTML حالا دادههای واکشی شده را با دستکاری DOM قابل مشاهده برای کاربران میکنیم. مثل فرایند ظهور عکس در اتاق تاریک، دادههای نامرئی را به چیزی تبدیل میکنیم که کاربران بتوانند ببینند و با آن تعامل کنند. دستکاری DOM تکنیکی است که صفحات وب ایستا را به برنامههای پویا تبدیل میکند که محتوای خود را بر اساس تعاملات کاربر و پاسخهای سرور بهروزرسانی میکنند. ### انتخاب ابزار مناسب برای کار وقتی صحبت از بهروزرسانی HTML با جاوااسکریپت است، چند گزینه دارید. اینها مانند ابزارهای مختلف در جعبه ابزار هستند - هر کدام برای کارهای خاصی عالیاند: | روش | چه کاری برایش عالی است | چه زمانی استفاده کنیم | سطح ایمنی | |--------|---------------------|----------------|--------------| | `textContent` | نمایش امن دادههای کاربر | هر زمانی که متن نمایش میدهید | ✅ بسیار قابل اعتماد | | `createElement()` + `append()` | ساختن طرحهای پیچیده | ایجاد بخشها/لیستهای جدید | ✅ کاملاً ایمن | | `innerHTML` | تعیین محتوای HTML | ⚠️ سعی کنید از این استفاده نکنید | ❌ خطرناک | #### روش امن نمایش متن: textContent خصوصیت [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) بهترین دوست شما هنگام نمایش دادههای کاربر است. این مثل یک نگهبان برای صفحه وب شماست - هیچ چیز مضر اجازه عبور ندارد: ```javascript // راه امن و قابل اعتماد برای بهروزرسانی متن const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **مزایای textContent:** - همه چیز را به عنوان متن ساده در نظر میگیرد (اجرا شدن اسکریپت را جلوگیری میکند) - به طور خودکار محتوای موجود را پاک میکند - برای بهروزرسانیهای متنی ساده کارآمد است - امنیت داخلی در برابر محتوای مخرب فراهم میکند #### ساخت عناصر HTML پویا برای محتواهای پیچیدهتر، [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) را با متد [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) ترکیب کنید: ```javascript // راه ایمن برای ایجاد عناصر جدید const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **درک این روش:** - عناصر DOM جدید را به صورت برنامهنویسی ایجاد میکند - کنترل کامل روی ویژگیها و محتوای عنصر دارد - اجازه ساختارهای پیچیده و تو در تو را میدهد - امنیت را با جدا کردن ساختار از محتوا حفظ میکند > ⚠️ **ملاحظه امنیتی**: در حالی که [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) در بسیاری آموزشها ظاهر میشود، میتواند اسکریپتهای جاسازی شده را اجرا کند. مانند پروتکلهای امنیتی CERN که اجازه اجرای کد غیرمجاز نمیدهند، استفاده از `textContent` و `createElement` جایگزینهای امنتری هستند. > **خطرات innerHTML:** - هر تگ `