פונקציות גנרטור ב-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
ניתן להגדיר את סוג הפונקציה של מחולל (generator) בפורמט הבא.
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
להמתנה לתוצאות של פעולות אסינכרוניות תוך המשך עיבוד לפי סדר. עם זאת, ב-TypeScript או JavaScript, משתמשים בדרך כלל ב-async/await
.
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 בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.