Kodax

البرمجة غير المتزامنة — 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);
اختبر فهمك