الخطوة 3 في تطبيق الجوال: عميل API
اربط تطبيق الدردشة لديك بالواجهة الخلفية Flask باستخدام fetch().
ما ستتعلمه
- إرسال طلبات HTTP باستخدام
fetch() - استخدام async/await في الشيفرة غير المتزامنة
- التعامل مع استجابات JSON
- معالجة الأخطاء في طلبات الشبكة
الخطوة 1: ضبط عنوان URL الأساسي لواجهة API
const API_BASE_URL = "http://10.0.2.2:5000";
أي عنوان URL تستخدم:
| البيئة | عنوان URL |
|---|---|
| محاكي Android | http://10.0.2.2:5000 |
| محاكي iOS | http://localhost:5000 |
| جهاز فعلي | http://YOUR_COMPUTER_IP:5000 |
| Expo web | http://localhost:5000 |
لمعرفة عنوان IP لجهاز الكمبيوتر:
# على نظام macOS/Linux
ip addr show | grep inet
# على نظام Windows
ipconfig
الخطوة 2: جلب الرسائل عند تحميل التطبيق
import { useEffect } from "react";
useEffect(() => {
fetchMessages();
}, []);
const fetchMessages = async () => {
try {
const response = await fetch(`${API_BASE_URL}/api/messages`);
const data: Message[] = await response.json();
setMessages(data);
} catch (err) {
console.error("Failed to fetch messages:", err);
}
};
- يعمل
useEffectمرة واحدة عند تحميل التطبيق (مصفوفة التبعيات[]تعني «مرة واحدة فقط») - يرسل
fetch()طلب GET إلى الواجهة الخلفية - تحلّل
response.json()جسم استجابة JSON
الخطوة 3: إرسال رسالة
استبدل الدالة المؤقتة handleSend من الخطوة 2:
const handleSend = async () => {
const text = input.trim();
if (!text) return;
setInput(""); // امسح حقل الإدخال فورًا
setError(null);
// أضف رسالة المستخدم إلى القائمة فورًا (تحديث تفاؤلي للواجهة)
const tempUser: Message = {
id: Date.now(),
content: text,
sender: "user",
};
setMessages((prev) => [...prev, tempUser]);
try {
const response = await fetch(`${API_BASE_URL}/api/chat`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text }),
});
if (!response.ok) {
const errData = await response.json();
throw new Error(errData.error || "Request failed");
}
const data = await response.json();
// استبدل الرسالة المؤقتة بالرسالة المؤكدة من الخادم، وأضف رد الذكاء الاصطناعي
setMessages((prev) =>
prev.map((m) =>
m.id === tempUser.id ? data.user_message : m
).concat(data.ai_message)
);
} catch (err: any) {
setError(err.message || "Failed to send message");
// ضع علامة على الرسالة التي فشل إرسالها
setMessages((prev) =>
prev.map((m) =>
m.id === tempUser.id
? { ...m, content: `${m.content} (failed)` }
: m
)
);
}
};
الخطوة 4: فهم fetch()
const response = await fetch(url, {
method: "POST", // طريقة HTTP
headers: {
"Content-Type": "application/json", // أخبر الخادم بأننا نرسل JSON
},
body: JSON.stringify({ message: text }), // حوّل الكائن إلى نص JSON
});
توقف الكلمة المفتاحية await التنفيذ مؤقتًا حتى تصل الاستجابة. وبدونها ستتابع الشيفرة التنفيذ قبل أن ينتهي الطلب.
الخطوة 5: معالجة الأخطاء
try {
// طلب شبكة
} catch (err) {
// حدث خطأ ما — لا توجد أي استجابة (خطأ في الشبكة)
}
هناك نوعان من الأخطاء:
1. خطأ في الشبكة — تعذّر الوصول إلى الخادم (يلتقطه catch)
2. خطأ HTTP — استجاب الخادم برمز حالة خطأ (تحقّق من response.ok)
الخطوة 6: اختبار الاتصال
- شغّل الواجهة الخلفية:
python app/__init__.py(من داخلbackend/) - شغّل تطبيق الجوال:
npx expo start(من داخلmobile/) - اكتب رسالة واضغط زر الإرسال
- تظهر الرسالة، ويُفترض أن يرد الذكاء الاصطناعي (إذا كنت قد أعددت OpenAI)
- إذا لم يرد الذكاء الاصطناعي: تحقّق من شريط الأخطاء
المشكلات الشائعة
"Network request failed" — لا يستطيع التطبيق الوصول إلى الواجهة الخلفية: - هل الواجهة الخلفية تعمل؟ - هل عنوان URL صحيح لمنصتك (محاكي أم جهاز فعلي)؟ - هل الجهازان على الشبكة نفسها؟
خطأ في تحليل JSON — الاستجابة ليست JSON صالحًا: - تحقّق من طرفية الواجهة الخلفية بحثًا عن أخطاء - اختبر باستخدام curl للتأكد من أن API يعمل