اپ تا الان هیچ درخواستی به سرور نمیزد و همهی دادهها داخلِ خودِ کامپوننتها
هاردکد بود. این کامیت لایهی ارتباط را اضافه میکند، بدونِ اینکه هیچ صفحهای
را تغییر دهد.
عمداً فقط فایلِ جدید اضافه شده و App.tsx دست نخورده است، چون کارِ در جریانِ
برنچِ updateApp روی همان فایل است و نباید با هم تصادف کنند. وصل کردنِ
صفحهها به این لایه کارِ بعدیست.
هیچ پکیجِ جدیدی اضافه نشد — فقط fetch استاندارد.
چیزهایی که در client.ts هست برای حالتِ خراباند، نه حالتِ خوب:
• timeout روی هر درخواست — وگرنه بکاندِ کند سوکتها را باز نگه میدارد تا
مرورگر به سقفِ ۶ درخواستِ همزمان بخورد و اپ قفل شود.
• backoff با jitter — بدونِ jitter همهی کلاینتها بعد از یک خطا همزمان
دوباره میزنند و موجِ دوم از موجِ اول بدتر است.
• تکرارِ خودکار فقط روی GET؛ POST فقط وقتی Idempotency-Key دارد (ثبتِ پاسخ،
سفارش) تا دابلکلیکِ کاربر دو بار XP یا دو سفارش نسازد.
• refresh تکنسخهای — ۲۰ درخواستِ همزمانِ ۴۰۱ نباید ۲۰ بار refresh بزنند.
• ادغامِ GETهای یکسانِ در جریان.
• احترام به هدرِ Retry-After که بکاند موقعِ throttle میفرستد.
credentials: 'omit' عمدیست: احرازِ هویت توکنِ Bearer در هدر است و سمتِ سرور
CORS_ALLOW_CREDENTIALS=False تنظیم شده.
.env هم به .gitignore اضافه شد؛ قبلاً فقط node_modules داخلش بود و آدرس/
تنظیماتِ محلی میتوانست ناخواسته کامیت شود.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.2 KiB
4.2 KiB
اتصال به بکاند
کلِ ارتباط با سرور از همین پوشه رد میشود. هیچجای اپ مستقیم fetch نزنید —
مدیریتِ توکن، تکرارِ درخواست و رفتارِ درستِ خطا اینجا یکجا حل شدهاند.
راهاندازی
هیچ تنظیماتی لازم نیست. بهطورِ پیشفرض به بکاندِ مشترک
(https://api.math.tadrisino2.ir/api) وصل میشود:
npm install
npm run dev
فقط اگر بکاند را روی ماشینِ خودتان بالا آوردهاید:
cp .env.example .env # و خطِ VITE_API_BASE_URL را باز کنید
برای اینکه ببینید اتصال برقرار است، یک خط کافیست (بعداً پاکش کنید):
import { ConnectionCheck } from '@/api/ConnectionCheck';
// داخلِ خروجیِ App:
<ConnectionCheck />
گوشهی صفحه سبز میشود و فهرستِ پایهها را از سرور نشان میدهد، یا قرمز میشود و میگوید دقیقاً کجای کار میلنگد.
استفاده
import { api, ApiError } from '@/api';
const grades = await api.grades();
const home = await api.home(); // پایهی خودِ کاربر
const intro = await api.lessons.intro(lessonId);
const answer = await api.ai.ask('این رو نفهمیدم', { lessonId });
ورود
await api.auth.guest(deviceId); // «شروع سریع»، بدونِ شماره
// یا
const { devOtp } = await api.auth.requestOtp('09120000000');
await api.auth.login('09120000000', otp); // نامِ فیلد در سرور otp است
توکن خودش در localStorage ذخیره میشود و به هر درخواست اضافه میگردد.
خطاها
try {
await api.ai.ask(text, { lessonId });
} catch (error) {
if (error instanceof ApiError) {
if (error.isRateLimited) { /* ۴۲۹ — خیلی سریع پرسیده */ }
if (error.isProviderDown) { /* ۵۰۳ — سرویسِ AI موقتاً قطع */ }
if (error.isNetwork) { /* اصلاً نرسید یا timeout */ }
}
}
چرا اینقدر ملاحظه در client.ts
هر تکهاش برای حالتیست که فقط زیرِ فشار پیش میآید:
| مسئله | اگر نباشد چه میشود |
|---|---|
timeout روی هر درخواست |
یک بکاندِ کند سوکتها را باز نگه میدارد؛ مرورگر به سقفِ ۶ درخواستِ همزمان میخورد و کلِ اپ قفل میشود |
| backoff با jitter | هزار کلاینت بعد از یک خطا همزمان دوباره میزنند و موجِ دوم سرور را میخواباند |
تکرارِ خودکار فقط روی GET |
تکرارِ POST یعنی سفارش یا پاسخِ تکراری |
Idempotency-Key روی ثبتِ پاسخ و سفارش |
دابلکلیکِ کاربر دو بار XP یا دو سفارش میسازد |
refresh تکنسخهای |
۲۰ درخواستِ همزمانِ ۴۰۱ ⇒ ۲۰ بار refresh ⇒ سرور همه را throttle میکند |
ادغامِ GETهای یکسان |
دو کامپوننت که با هم یک چیز میخواهند، دو برابر بار میسازند |
احترام به هدرِ Retry-After |
بکاند صریح میگوید چقدر صبر کن؛ نادیده گرفتنش throttle را طولانیتر میکند |
credentials: 'omit' هم عمدیست: احرازِ هویت توکنِ Bearer در هدر است و سمتِ
سرور CORS_ALLOW_CREDENTIALS=False تنظیم شده. عوضش نکنید.
چیزی که هنوز نیست
- صفحهی ورود در اپ وجود ندارد؛
api.authآماده است ولی UI ندارد. api.home()ساختارِ واقعیِ درسها را میدهد، ولی وصل کردنش به صفحهها هنوز انجام نشده — این PR عمداًApp.tsxرا دست نزده تا با کارِ در جریان تصادف نکند.