תוכן עניינים
שפת הסקריפט Javascript עושה עוד צעד בדרך להיותה שפה שלמה עם פיצ'ר חדש ומבטיח: Web Workers
אחת מנקודות התורפה הגדולות ביותר של Javascript היא היותה שפה שרצה על תהליכון אחד. משתמע מכך: ג'אווה סקריפט לא יכולה להריץ מס' סקריפטים במקביל.
נכון, ניתן "לדמות" מקביליות בשפה באמצעות שימוש בטכניקות כמו setInterval(), setTimeOut() ו – XMLHttpRequest(),
אבל כל הפונקציות הללו מאפשרות ריצה א-סינכרונית ולא ריצה מקבילית.
נקודת התורפה הזו מורגשת היטב באפליקציות שעושות שימוש "כבד" ב – Javascript.
פעולות מורכבות עלולות להאט במקרה הטוב ולתקוע את הדף במקרה הרע למס' שניות ואף דקות. בעולם שבו חוויית המשתמש באה לפני הכל – מדובר באסון!
Web Workers: חלוקה טובה יותר של המשאבים
תחשבו על זה ככה: Web Workers מאפשרים "להוסיף" ל – JS עוד "מעבדים" וע"י כך לקיים ריצה מקבילית של הסקריפט.
מכיוון שכל Web Worker (בעברית: פועל) תלוי בעצמו בלבד, הדף שהמשתמש ביקש לטעון לא נאלץ לחכות לסיום הריצה, ויכול להמשיך בטעינה.
הפוטנציאל הוא עצום: Web Workers מאפשר לנו לפרק את הסקריפט למס' תהליכונים שרצים ברקע וע"י כך להביא, פוטנציאלית, לשיפור מהירות הטעינה,
ולחוויית משתמש טובה הרבה יותר.
במציאות של היום, בה Javascript הופכת לשפה משמעותית יותר ויותר, הכלי הופך לחיוני ואף הכרחי.
Web Workers – מה הם יכולים לעשות?
מכיוון שכל פועל עומד בפני עצמו ולא תלוי בסקריפט אחר,
לא ניתן לאפשר לו גישה לכל הפיצ'רים שקיימים בג'אווה סקריפט.
לכן, פועל לא יוכל לבצע את הפעולות הבאות:
- מניפולציות DOM
- לגשת לאובייקט window
- לגשת לאובייקט document
- לשגת לאובייקט parent
לעומת זאת, פועל יוכל לבצע את הפעולות הבאות:
- לגשת לאובייקט navigator
- לגשת לאובייקט location (קריאה בלבד)
- לבצע בקשות http
- לבצע אינטרוואלים
- לבצע מניפולציות זמן
ישנם שני סוגים של web workers:
Dedicated Web Workers
לפועל ייעודי (Dedicated Web Worker) ניתן לגשת רק מתוך הסקריפט שיצר אותו.
זאת אומרת שאם ניגש לאותו ה – Web Worker משני סקריפטים שונים, שני מופעים שונים של אותו Web Worker יווצרו.
לעומת הפועל הייעודי, ב – SharedWorker (או בעברית: פועל שיתופי) קיים scope אחד גלובלי, מה שמאפשר בעצם תקשורת בין שני סקריפטים שונים באמצעותו.
ללא ספק, הפועל השיתופי טומן בחובו פוטנציאל אדיר. עם זאת – נכון לכתיבת שורות אלה הוא פחות נתמך (בישראל רק כ – 48% מהמשתמשים, לעומת כמעט 98% שתומכים בפועל ייעודי).
מכיוון שאחוזי התמיכה ב – Shared Workers נמוך בשלב זה, אתייחס בפוסט ל – Dedicated Web Workers:
מורה נבוכים – Web Workers
התקשורת שנוצרה מתבצעת בין שני גורמים: הפועל וסקריפט האב.
יצירת Web Worker
מכיוון שפועלים רצים בנפרד, יש לכתוב את הסקריפט שלהם בקובץ נפרד. ניצור את הפועל באופן הבא:
1 |
var worker = new Worker("worker.js"); |
כבר בנקודה הזו, אנו מקבלים טעימה ראשונה מתכונותיו של הפועל:
אם הקובץ לא נמצא, המשתמש לא ירגיש בכך. הסקריפט "יקרוס" בשקט.
אם הקובץ כן נמצא, תהליכון חדש ייווצר – אך לא יתחיל לרוץ.
* לא ניתן לטעון קובץ משרת מרוחק.
הפעלת Web Worker
כדי להפעיל Web Worker, נקרא לפונקציה postMessage()
1 2 3 4 |
var worker = new Worker('worker.js'); worker.postMessage(); |
פעולה זו מתחילה את הריצה של הפועל כאשר נקראת לראשונה.
תקשורת דו-כיוונית בין סקריפט האב לפועל
הפונקציה postMessage() אחראית לא רק להתחלת הריצה, אלא גם למעבר נתונים בין הפועל לסקריפט האב – ולהפך.
כאשר נרצה לשלוח מחרוזת מאחד הצדדים לשני, נשתמש בפונקציה:
1 2 3 4 5 6 |
//נצא מנקודת הנחה שהמשתנה form מכיל את אלמנט הטופס; המשתנה formInputs מכיל אובייקט עם שדות הטופס form.addEventListener("submit", function() { worker.postMessage(formInputs); }); |
בדוגמה הזאת, אנו שולחים את הטופס לעיבוד ב – Web Worker, ובינתיים נוכל להתחיל את טעינת העמוד הבא במקביל לעיבוד טופס ההזמנה.
האזנה לקלט
האזנה לקלט נתונים מהפועל לסקריפט האב תתבצע באמצעות הוספת מאזין למשתנה worker, שיאזין לאירוע 'message':
1 2 3 4 5 6 |
var worker = new Worker('worker.js'); worker.addEventListener('message', function(e) { console.log('Worker Says: ', e.data) }, false); |
האזנה לקלט נתונים מסקריפט האב לפועל תתבצע כפי שמתבצע בכיוון ההפוך, אלא שבמקום להוסיף את ההאזנה למשתנה worker (שלא קיים בפועל עצמו) – נשתמש ב – self:
1 2 3 4 5 |
self.addEventListener('message', function(e) { console.log('Script Says: ', e.data) }, false); |
הגבלת פלט
את הפלט ניתן להעביר באמצעות הסוגים הבאים:
- File
- Blob
- ArrayBuffer
- Json
- String
יש לשים לב שככל שהפלט כבד יותר, כך יקח לו יותר זמן "להגיע" לצד השני, מכיוון שהצד השני יוצר עותק חדש של הפלט.
כאשר הבעיה הופכת לרלוונטית, ניתן להתמודד איתה באמצעות חלוקת הפלט לחלקים או באמצעות שימוש ב – Transferable Objects.
טעינת סקריפט חיצוני לתוך Web Worker
ניתן לטעון סקריפטים / ספריות שונות לתוך הפועל באמצעות השימוש בפונקציה importScript():
1 2 3 |
importScripts('script1.js', 'script2.js'); |
התמודדות עם שגיאות
נתמודד עם שגיאות שנוצרו באמצעות הוספת מאזין למשתנה worker, שיאזין לאירוע error:
1 2 3 4 5 6 |
var worker = new Worker('worker.js'); worker.addEventListener('error', function(e) { console.log(e); // {filename: 'worker.js', lineno: 55, message: '...'} }, false); |
מתי נשתמש
ניתן להשתמש ב – Web Workers למגוון רחב מאד של משימות.
ככל שהזמן יעבור – נחשף לעוד ועוד מקרי שימוש ב – Web Worker – השמיים הם הגבול.
המטרה מאחורי הפיצ'ר היא להעביר משימות מורכבות יותר לרקע ובכך למנוע פגישה בממשק המשתמש:
- עיבוד כמויות מידע גדולות – תמונות, טפסים וכו'
- חישובים מרוכבים
- ניתוח וידאו / אודיו
- משחקי WEB
- ועוד
לסיכום
בפוסט השתדלתי לעבור על התכונות הבסיסיות ביותר של Web Workers API.
למעוניינים להעמיק, באתר HTML5 ROCK כתבו פוסט נרחב על הפיצ'ר החדש.
אין ספק שמדובר במהפכה שמקרבת את שפת Javascript לכדי שליטה בעולם ה – WEB והופכת את השפה למתקדמת יותר ומותאמת יותר לצרכים העכשוויים של הווב.
אז קדימה – תתחילו לעבוד! 🙂


0 תגובות