כש-javascript רץ צריך לזכור ולהבין שהוא single threaded, זה אומר שהוא מטפל בכל שורה בזמן שהוא קורא אותה, אז השאלה הברורה היא, מה הוא עושה כאשר יש לו פונקציה לא סנכרונית?
settimeout עושה את זה בדיוק, גם אם הוא 0, עדיין הפונקציה הופכת ל-async, זאת אומרת שהתשובה מהפונקציה תחזור אחרי שנקודת הקריאה של הסקריפט כבר ממש לא שם וכנראה מטפלת בשורת קוד אחרת.
מיד נכיר את queue ואת stack , בעזרת שניהם ג'אווה-סקריפט מטפל בהכל.
queue
מיצג את התור להפעלה, שיטת העבודה שלו היא:
ראשון נכנס – ראשון יוצא
stack
מיצג את הערימה להפעלה שיטת העבודה שלו היא:
אחרון נכנס – ראשון יוצא
בנוסף לתור ולערימה יש לנו את המצביע (יש גם את event loop).
single thread
הוא המצביע (מצביע יחיד) שרץ שורה אחרי שורה בקוד ומוציא אותה לפועל.
בנוסף לתור ולערימה יש לנו את המצביע (יש גם את event loop).
כל שורה נכנסת לערימה ומופעלת, כך שאם יש לי פונקציה שקוראת לפונקציה שקוראת לעוד אחת זה יראה כך:
- פונקציה 3
- פונקציה 2
- פונקציה 1
זה אומר, שהוא יריץ את פונקציה 3 שהיא האחרונה בשרשרת ונקראה מתוך פונקציה 2, אחרי זה ימשיך להריץ את שאר השורות שנשארו בפונקציה 2 ואחרי זה לפונקציה 1.
אבל מה שקורה בפונקציות לא סנכרויות הוא:
כאשר צריך את השורה של פונקציה לא סנכרונית, זה אומר שלא ידוע מתי התשובה שלה תחזור,
היא נשלחת ל-API של הדפדפן שמטפל בעצמו בכל דבר לא סנכרוני וכאשר הוא מסתיים, כדי לא להפריע לריצה של הערימה, הוא מעביר את התשובה של הפונקציה לתור.
בין הערימה לתור יש לולאה (even loop) שבודקת את מצב הערימה, אם היא ריקה ורק אם היא ריקה, הלולאה פונה לתור.
אם יש משהו בתור, הוא מועבר לערימה ושם הוא מוצא לפועל.
ולכן כאשר אנחנו נכתוב את הקוד הבא:
function logit() { console.log('1'); setTimeout(() => { console.log('2'); }, 0); console.log('3'); } logit();
אנחנו נקבל הדפסה של 1, אחרי זה 3 ולבסוף 2.
למרות שזמן ההפסקה שלנו 0 בשורה 3 מה שקורה הוא:
- שורה מספר 2 מופעלת
- שורה מספר 3 נשלחת ל-API של הדפדפן ומשם לתור
- שורה מספר 4 מופעלת
ועכשיו כאשר הערימה ריקה, ה-event loop מעביר את ה-callback של ה-timeout חזרה לערימה ושם הוא מופעל.
עכשיו לשאלה, למה זה טוב לנו?
זו דרך מאוד טובה לגרום לקוד לרוץ בסוף אחרי כולם מבלי להוסיף לו זמן, בדיקה וסימולציה של הגעת מידע סטטי כמידע מבסיס נתונים שאמור להגיע כ-async.
בכלל, זו שיטה נוספת לשלוט בקוד שלנו ולהחליט מתי דברים רצים.