التزامن وتعدد الخيوط في TypeScript: من النظرية إلى التطبيق
تتطلب تطبيقات الويب الحديثة أداءً عاليًا. يوفر TypeScript، الذي يعمل فوق Node.js، أدوات قوية لمعالجة مهام متعددة في وقت واحد. في هذه المقالة، سنشرح كيفية عمل التزامن وتعدد الخيوط في TypeScript، ونتعلم كيفية تطبيقها عمليًا.
التزامن مقابل التوازي: الاختلافات الرئيسية
قبل التعمق في الكود، من المهم فهم الفرق بين التزامن والتوازي.
- التزامن — هو قدرة البرنامج على معالجة مهام متعددة عن طريق التبديل بينها. في JavaScript/TypeScript، يتم تحقيق ذلك من خلال Event Loop والعمليات غير المتزامنة.
- التوازي — هو التنفيذ المتزامن لمهام متعددة على أنوية معالج مختلفة. في Node.js، يتم تحقيق ذلك من خلال Worker Threads.
TypeScript (مثل JavaScript) هو أحادي الخيط بطبيعته، ولكن بفضل العمليات غير المتزامنة و Worker Threads، يمكننا استخدام كلا النهجين بفعالية.
البرمجة غير المتزامنة: أساس التزامن في TypeScript
البرمجة غير المتزامنة هي الخطوة الأولى نحو التزامن. دعنا نستعرض الآليات الأساسية.
Promises و async/await
يستخدم TypeScript الحديث async/await بنشاط للعمل مع العمليات غير المتزامنة. يتيح ذلك كتابة كود يبدو متزامنًا ولكنه يُنفذ بشكل متزامن.
// مثال على دالة غير متزامنةasync function fetchData(url: string): Promise<any> { const response = await fetch(url); return response.json();}
// تشغيل متزامن لعدة طلباتasync function fetchAllData(): Promise<void> { const [users, posts, comments] = await Promise.all([ fetchData('/api/users'), fetchData('/api/posts'), fetchData('/api/comments') ]); console.log('تم تحميل جميع البيانات بشكل متزامن');}يتيح Promise.all تشغيل عدة عمليات غير متزامنة في وقت واحد، مما يسرع التنفيذ بشكل كبير مقارنة بالتشغيل التسلسلي.
معالجة الأخطاء في الكود غير المتزامن
من المهم معالجة الأخطاء بشكل صحيح عند التنفيذ المتزامن:
async function safeFetchAll(): Promise<void> { try { const results = await Promise.allSettled([ fetchData('/api/users'), fetchData('/api/invalid'), fetchData('/api/posts') ]); results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`الطلب ${index} ناجح:`, result.value); } else { console.error(`الطلب ${index} فشل:`, result.reason); } }); } catch (error) { console.error('خطأ حرج:', error); }}Worker Threads: تعدد خيوط حقيقي في TypeScript
للمهام كثيفة الاستخدام للمعالج (معالجة الصور، الحسابات المعقدة)، لا تكفي البرمجة غير المتزامنة وحدها. هنا تأتي Worker Threads للإنقاذ — وهي خيوط تنفيذ حقيقية.
إنشاء Worker Thread
لننظر إلى مثال لحساب أرقام فيبوناتشي في خيط منفصل:
// fibonacci.worker.tsimport { parentPort } from 'worker_threads';
function fibonacci(n: number): number { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2);}
parentPort?.on('message', (n: number) => { const result = fibonacci(n); parentPort?.postMessage(result);});// main.tsimport { Worker } from 'worker_threads';import path from 'path';
function runFibonacci(n: number): Promise<number> { return new Promise((resolve, reject) => { const worker = new Worker(path.resolve(__dirname, 'fibonacci.worker.ts')); worker.postMessage(n); worker.on('message', (result: number) => { resolve(result); worker.terminate(); }); worker.on('er