التزامن وتعدد الخيوط في TypeScript: دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التزامن وتعدد الخيوط في TypeScript: من النظرية إلى التطبيق



تطبيقات الويب الحديثة تواجه بشكل متزايد الحاجة إلى معالجة كميات كبيرة من البيانات وتنفيذ عمليات كثيفة الاستخدام للموارد دون حظر واجهة المستخدم. TypeScript، كونه طبقة فوقية على JavaScript، يرث نموذج التنفيذ أحادي الخيط الخاص به، لكنه يوفر أدوات قوية لتنظيم التزامن وتعدد الخيوط. في هذه المقالة، سنشرح كيفية استخدام هذه الإمكانيات بفعالية في مشاريعك.



فهم التزامن وتعدد الخيوط



قبل التعمق في الكود، من المهم التمييز بين مفهومين رئيسيين:



  • التزامن — قدرة النظام على معالجة عدة مهام في فترات زمنية متداخلة، ولكن ليس بالضرورة في نفس الوقت. يتم تحقيق ذلك من خلال التبديل السريع للسياق.
  • تعدد الخيوط — التنفيذ المتوازي لعدة خيوط على أنوية معالج مختلفة. في Node.js، يتم تحقيق ذلك من خلال Worker Threads.


يعمل TypeScript في بيئة Node.js، حيث يقوم الخيط الرئيسي بمعالجة الأحداث عبر Event Loop. بالنسبة للحسابات الثقيلة، يمكن أن يصبح هذا عنق زجاجة.



عدم التزامن و Promise: أساس التزامن



المستوى الأساسي للتزامن في TypeScript يُبنى على async/await و Promise. تسمح هذه الآليات بعدم حظر الخيط الرئيسي أثناء انتظار عمليات الإدخال/الإخراج.



// مثال على تحميل البيانات بشكل غير متزامنinterface User {  id: number;  name: string;}

async function fetchUser(id: number): Promise<User> { const response = await fetch(`https://api.example.com/users/${id}`); return response.json();}

// تشغيل متوازي لعدة طلباتasync function loadUsers(): Promise<User[]> { const userIds = [1, 2, 3, 4, 5]; const promises = userIds.map(id => fetchUser(id)); return Promise.all(promises);}

loadUsers().then(users => { console.log('تم تحميل المستخدمين:', users.length);});


يقوم Promise.all بتشغيل جميع الوعود في وقت واحد، لكنها تُنفذ في خيط واحد. هذا مثالي لمهام الإدخال/الإخراج، لكنه غير مناسب للعمليات المكثفة لوحدة المعالجة المركزية.



Worker Threads: تعدد خيوط حقيقي



لتنفيذ حسابات ثقيلة دون حظر الخيط الرئيسي، استخدم Worker Threads. هذه وحدة مدمجة في Node.js تنشئ خيوطًا منفصلة بذاكرة خاصة بها.



لنقم بإنشاء مثال لحساب أرقام فيبوناتشي في خيط منفصل:



// 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 runFibonacciInWorker(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', resolve); worker.on('error', reject); worker.on('exit', (code) => { if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`)); }); });}

async function main() { console.time('fibonacci'); const result = await runFibonacciInWorker(40); console.timeEnd('fibonacci'); console.log(`Fibonacci(40) = ${result}`);}

main();


لاحظ: لتشغيل عمال TypeScript، ستحتاج إلى تجميعها إلى JavaScript. يمكنك استخدام ts-node أو التجميع المسبق.



SharedArrayBuffer: ذاكرة مشتركة بين الخيوط



عندما تحتاج الخيوط إلى تبادل كميات كبيرة من البيانات

المدونات

توصيات الكتب