البرمجة غير المتزامنة — JavaScript الأساسيات
البرمجة غير المتزامنة
JavaScript تعمل بخيط واحد (Single Thread)، لذا نحتاج البرمجة غير المتزامنة للعمليات الطويلة.
لماذا نحتاجها؟
- طلبات الشبكة (API calls)
- قراءة الملفات
- Timers
- أحداث المستخدم
Callbacks (الطريقة القديمة)
// setTimeout - تأخير التنفيذ
setTimeout(() => {
console.log("بعد ثانيتين");
}, 2000);
// setInterval - تكرار
const intervalId = setInterval(() => {
console.log("كل ثانية");
}, 1000);
// إيقاف التكرار
clearInterval(intervalId);
// Callback Hell 😱 (توضيح: getData و processA... دوال افتراضية تأخذ callback)
function loadEverything() {
getData(function(a) {
processA(a, function(b) {
processB(b, function(c) {
processC(c, function(d) {
// 🔥 Pyramid of Doom!
});
});
});
});
}Promises (الحل الأفضل)
// إنشاء Promise
const myPromise = new Promise((resolve, reject) => {
// عملية غير متزامنة
setTimeout(() => {
const success = true;
if (success) {
resolve("نجحت العملية! ✅");
} else {
reject("فشلت العملية ❌");
}
}, 1000);
});
// استخدام Promise
myPromise
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log("انتهت العملية");
});Promise Chaining
fetch("/api/user")
.then(response => response.json())
.then(user => {
console.log(user);
return fetch(`/api/posts/${user.id}`);
})
.then(response => response.json())
.then(posts => {
console.log(posts);
})
.catch(error => {
console.error("خطأ:", error);
});Promise Methods
const promise1 = fetch("/api/users");
const promise2 = fetch("/api/posts");
const promise3 = fetch("/api/comments");
// Promise.all - انتظار الكل (تفشل إذا فشل واحد)
Promise.all([promise1, promise2, promise3])
.then(([users, posts, comments]) => {
console.log("كل البيانات:", users, posts, comments);
})
.catch(error => {
console.error("فشل أحدها:", error);
});
// Promise.allSettled - انتظار الكل (حتى لو فشل بعضها)
Promise.allSettled([promise1, promise2, promise3])
.then(results => {
results.forEach(result => {
if (result.status === "fulfilled") {
console.log("نجح:", result.value);
} else {
console.log("فشل:", result.reason);
}
});
});
// Promise.race - أول واحد ينتهي
Promise.race([promise1, promise2])
.then(firstResult => {
console.log("الأول:", firstResult);
});
// Promise.any - أول واحد ينجح
Promise.any([promise1, promise2])
.then(firstSuccess => {
console.log("أول نجاح:", firstSuccess);
});Async/Await (الأفضل) ⭐
// دالة async
async function fetchUserData() {
try {
const response = await fetch("/api/user");
const user = await response.json();
const postsResponse = await fetch(`/api/posts/${user.id}`);
const posts = await postsResponse.json();
return { user, posts };
} catch (error) {
console.error("خطأ:", error);
throw error;
}
}
// استخدام
fetchUserData()
.then(data => console.log(data))
.catch(error => console.error(error));
// أو
async function main() {
const data = await fetchUserData();
console.log(data);
}
main();Async/Await المتوازي
// ❌ تسلسلي (بطيء): كل طلب ينتظر انتهاء الذي قبله
async function fetchSequential() {
const usersRes = await fetch("/api/users");
const postsRes = await fetch("/api/posts");
return [await usersRes.json(), await postsRes.json()];
}
// ✅ متوازي (أسرع): الطلبات تنطلق معاً
async function fetchAll() {
const [usersRes, postsRes, commentsRes] = await Promise.all([
fetch("/api/users"),
fetch("/api/posts"),
fetch("/api/comments")
]);
const users = await usersRes.json();
const posts = await postsRes.json();
const comments = await commentsRes.json();
return { users, posts, comments };
}Fetch API
// GET Request
async function getUsers() {
const response = await fetch("https://api.example.com/users");
const data = await response.json();
return data;
}
// POST Request
async function createUser(userData) {
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(userData)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
// مع Error Handling كامل
async function fetchWithErrorHandling(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
return { data, error: null };
} catch (error) {
return { data: null, error: error.message };
}
}مثال عملي: تطبيق أخبار
class NewsApp {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = "https://newsapi.org/v2";
}
async getTopHeadlines(country = "us") {
try {
const url = `${this.baseUrl}/top-headlines?country=${country}&apiKey=${this.apiKey}`;
const response = await fetch(url);
const data = await response.json();
if (data.status === "error") {
throw new Error(data.message);
}
return data.articles;
} catch (error) {
console.error("فشل جلب الأخبار:", error);
return [];
}
}
async searchNews(query) {
const url = `${this.baseUrl}/everything?q=${encodeURIComponent(query)}&apiKey=${this.apiKey}`;
const response = await fetch(url);
return await response.json();
}
}
// استخدام
const app = new NewsApp("YOUR_API_KEY");
const headlines = await app.getTopHeadlines("ae");
console.log(headlines);// Promise بسيط
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
// Async/Await
async function demo() {
console.log("بداية...");
await delay(1000);
console.log("بعد ثانية");
await delay(1000);
console.log("بعد ثانيتين");
console.log("انتهى!");
}
demo();
// Fetch مثال
async function getUser(id) {
try {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users/${id}`
);
const user = await response.json();
console.log("المستخدم:", user.name);
return user;
} catch (error) {
console.error("خطأ:", error);
}
}
getUser(1);اختبر فهمك