دوال المُولدات في TypeScript
توضح هذه المقالة دوال المُولدات في TypeScript۔
يمكنك تعلم كل شيء من أساسيات كيفية استخدام دوال المولد إلى أمثلة متقدمة مدمجة مع المعالجة غير المتزامنة، بالإضافة إلى أمثلة برمجية.۔
YouTube Video
دوال المُولدات
تقدم دوال المُولدات في TypeScript وظائف مشابهة لدوال المُولدات في JavaScript۔ يتم تعريف دوال المُولدات باستخدام function*
(تصريح دالة مع علامة النجمة) وهي دوال خاصة يمكنها التوقف واستئناف التنفيذ على عكس الدوال العادية۔
عند استدعاء دالة المُولد، يتم إرجاع مكرر يقوم بإنشاء القيم واحدة تلو الأخرى، ويمكنك إيقاف التنفيذ باستخدام كلمة yield
المفتاحية أو إرسال قيم من الخارج۔
الصياغة الأساسية لدوال المُولدات
1function* myGenerator(): Generator<number, void, unknown> {
2 yield 1;
3 yield 2;
4 yield 3;
5}
6
7const gen = myGenerator();
8
9console.log(gen.next().value); // 1
10console.log(gen.next().value); // 2
11console.log(gen.next().value); // 3
12console.log(gen.next().done); // true (Iteration finished)
- تعريف دالة مُولد باستخدام
function* myGenerator()
۔ - توقف كلمة
yield
المفتاحية تنفيذ الدالة أثناء إرجاع قيمة۔ - في كل مرة يتم استدعاء طريقة
next()
، يستأنف تنفيذ دالة المُولد وتتقدم إلى الموضع التالي لـyield
۔
next()
تُرجع كائنًا يحتوي على القيمة التالية وخصيصة done
۔ عندما تكون done
تساوي true
، فهذا يشير إلى أنه تم إنشاء جميع القيم وانتهاء معالجة المُولد۔
تطبيقات دوال المُولدات
يتيح استخدام دوال المُولدات تمثيل عملية المعالجة التسلسلية بسهولة۔ في المثال التالي، نُنشئ دالة مُولد تولّد تسلسلًا من الأرقام۔
1function* sequenceGenerator(start: number = 0, step: number = 1) {
2 let current = start;
3 while (true) {
4 yield current;
5 current += step;
6 }
7}
8
9const seq = sequenceGenerator(1, 2);
10
11console.log(seq.next().value); // 1
12console.log(seq.next().value); // 3
13console.log(seq.next().value); // 5
- في هذا المثال، تولد
sequenceGenerator
تسلسلًا متزايدًا إلى ما لا نهاية من الأرقام۔ استخدمyield
لإرجاع القيم عند كل خطوة، وقم بتوليد القيمة التالية في الاستدعاءات اللاحقة۔
تمرير القيم إلى next
يمكن لطريقة next()
استلام قيمة، والتي يمكن إرسالها إلى داخل دالة المُولد۔
1function* adder() {
2 const num1 = yield;
3 const num2 = yield;
4 yield num1 + num2;
5}
6
7const addGen = adder();
8addGen.next(); // Initialization
9addGen.next(5); // Set 5 to num1
10const result = addGen.next(10).value; // Set 10 to num2 and get result
11console.log(result); // 15
- في هذا المثال، تقوم
next(5)
وnext(10)
بإرسال القيم الخاصة بهما إلى داخل دالة المُولد، بينما تعيدyield num1 + num2
مجموعهما۔
return
وthrow
return(value)
يمكن أن تُنهي المُولد وتعيد القيمة المحددة۔throw(error)
يمكن أن تولّد استثناءً داخل المُولد، وتُستخدم للتعامل مع الاستثناءات داخله۔
1function* testGenerator() {
2 try {
3 yield 1;
4 yield 2;
5 } catch (e) {
6 console.error("Error caught:", e);
7 }
8}
9
10const gen = testGenerator();
11console.log(gen.next().value); // 1
12gen.throw(new Error("An error occurred!")); // Error caught: An error occurred!
- في هذا المثال، تُستخدم طريقة
throw
لتوليد خطأ داخل المُولد، ويتم التقاط ذلك الخطأ داخل المُولد۔
تعريف النوع في TypeScript
يمكن تحديد تعريف النوع لدالة المولد بالتنسيق التالي۔
1// Generator<YieldType, ReturnType, NextType>
2function* myGenerator(): Generator<number, void, unknown> {
3 yield 1;
4 yield 2;
5 yield 3;
6}
- تقوم بتحديد الأنواع بالشكل
Generator<YieldType, ReturnType, NextType>
۔YieldType
هو نوع القيمة التي يُرجعهاyield
۔ReturnType
هو نوع القيمة التي يُرجعهاreturn
۔NextType
هو نوع القيمة التي يتم تمريرها إلىnext()
۔
في المثال التالي، يتم تحديد أنواع محددة لاستخدام المولّد بأمان مع الأنواع۔
1function* numberGenerator(): Generator<number, void, number> {
2 const num1 = yield 1;
3 const num2 = yield num1 + 2;
4 yield num2 + 3;
5}
6
7const gen = numberGenerator();
8
9console.log(gen.next().value); // 1
10console.log(gen.next(10).value); // 12 (10 + 2)
11console.log(gen.next(20).value); // 23 (20 + 3)
المولدات والمعالجة غير المتزامنة
يمكن أيضًا استخدام المولدات للمعالجة غير المتزامنة۔ على سبيل المثال، يمكنك استخدام yield
للانتظار للحصول على نتائج العمليات غير المتزامنة مع الاستمرار في التنفيذ التسلسلي۔ ومع ذلك، فإن async/await
تُستخدم بشكل أكثر شيوعًا في TypeScript أو JavaScript۔
1function* asyncTask() {
2 const result1 = yield fetch("https://codesparklab.com/json/example1.json");
3 console.log(result1);
4
5 const result2 = yield fetch("https://codesparklab.com/json/example2.json");
6 console.log(result2);
7}
لذلك، على الرغم من إمكانية معالجة العمليات غير المتزامنة بشكل تسلسلي باستخدام المولدات، إلا أنها لا تُستخدم كثيرًا لهذا الغرض بسبب أن Promises و async
/await
أكثر ملاءمة۔
الملخص
- دوال المولد هي دوال خاصة تُعرف باستخدام
function*
ويمكنها إرجاع قيم باستخدامyield
أثناء إيقاف تنفيذ الدالة مؤقتًا۔ - استخدم
next()
لاستئناف المولد واستلام القيم۔ بالإضافة إلى ذلك، يمكنك إرسال قيم إلى المولد باستخدامnext(value)
۔ - يمكنك استخدام
return()
وthrow()
لإنهاء دوال المولد أو لمعالجة الأخطاء۔ - عند استخدام المولدات في TypeScript، يمكنك الاستفادة من تعريفات النوع لكتابة تعليمات برمجية آمنة من حيث النوع۔
المولدات هي أدوات قوية تتيح لك التحكم بمرونة في التكرار۔
يمكنك متابعة المقالة أعلاه باستخدام Visual Studio Code على قناتنا على YouTube.۔ يرجى التحقق من القناة على YouTube أيضًا.۔