מדריך Node.js: קוד אסינכרוני

קוד סינכרוני וקוד אסינכרוני עם Node.js. מה זה ומה המשמעות של זה.
Node.js Logo

במאמר הקודם למדנו על סביבת העבודה של Node.js – איך מתקינים את Node.js על לינוקס או על חלונות. ואיך עובדים על Node.js באמצעות יצירת קובץ js והרצה שלו עם nodejs.

כשאנחנו מדברים על קוד JS, אנחנו מדברים על קוד סינכרוני וקוד אסינכרוני כאשר ב-Node.js אנו משתמשים בקוד אסינכרוני. על מנת להמחיש את כל הסינית הזו, אני רוצה להציג בפניכם קוד קטן של Node.js. הקוד הזה מבצע עבודה מול מערכת הקבצים.

על מנת לבצע את רוב הפעולות ב-node.js אנו קוראים למודולים. המודולים יכולים להגיע ב-core או להטען מבחוץ. אחד המודולים היותר חשובים הוא המודול שעוזר ל-node.js להתעסק עם הקבצים ושמו בישראל הוא fs – יעני file system 🙂 איך אנו קוראים למודולים? באמצעות require – אני ארחיב מאוד על מודולים בהמשך. אבל בוא בינתיים נרגע קצת ונסתכל על הקוד המאוד פשוט הזה:


var fs = require('fs');

filenames = fs.readdirSync(".");
for (i = 0; i < filenames.length; i++) {
    console.log(filenames[i]);
}

processId = process.getuid();
console.log(processId);

מה הקוד הזה עושה? לא צריך להיות מהנדס טילים כדי לדעת שמה שהוא עושה זה להדפיס את רשימת הקבצים שיש בתיקיה. בסופו של יום הוא מדפיס את ה-process id. מה הבעיה עם הקוד הזה? אין בעיה בכלל. מה הפלט שלו? על מנת לראות את הפלט שלו אני אשמור אותו כ:test_sync.js ואריץ אותו באמצעות nodejs test_sync.js. מה יצא לי בסוף מזה?


$ nodejs test.js 
test.js
test_sync.js
1000

מה אני מקבל פה? את רשימת הקבצים בתיקיה שלי (במקרה הזה test.js וכמובן test_sync.js) ואז מספר שמציין את ה-ProcessId. לא משהו שצריך להפיל אתכם.

מדובר פה בקוד סינכרוני – זה קוד שכל מי שמתכנת JS יותר מיום אמור להכיר. הבעיה היא (או יותר נכון היתרון האדיר של Node.js) שאנו אמורים לכתוב את הקוד כקוד א-סינכרוני. האמת היא שמודול fs הוא אחד המודולים הבודדים שמאפשרים לכתוב קוד סינכרוני. למה אנחנו אמורים לכתוב קוד אסינכרוני? כי קוד סינכרוני תוקע לנו את המערכת. אם נסתכל על הקוד שלעיל, אנו נראה שיש שם בת'כלס שתי פעולות – הדפסת הקבצים, שמותנית בקריאה של התיקיה שבה אנו נמצאים והדפסת ה-processId. כאשר אנו כותבים קוד סינכרוני אנחנו בעצם תוקעים את המערכת ולא מאפשרים לשאר הפעולות להעשות. התקיעה היא לא בהדפסה של שמות הקבצים אלא בהמתנה הארוכה ל-fs כדי שיקרא את רשימת הקבצים.

הרבה יותר חכם לעשות משהו בסגנון הזה – נבצע קריאה ל-fs כדי שיקרא את רשימת הקבצים – עד שהקריאה תושלם, נמשיך במורד הסקריפט. ברגע שהקריאה מושלמת, נוכל להשלים את כל הפעולות שכרוכות בקריאה הזו.

איך עושים את זה? באמצעות callbacks. זה סינטקס שאמור להיות מוכר מאוד לכל מי שהתעסק ב-jQuery בכלל וב-AJAX בפרט. מה שאנחנו עושים זה לקרוא ל-fs ואז לומר – 'מר בחור, עד שתסיים עם הקריאה מה-fs ותשיג לי את כל המידע – תמשיך את הסקריפט ואל תחכה'. איך עושים את זה?


var fs = require('fs');

fs.readdir(".", function (err, filenames) {
    var i;
    for (i = 0; i < filenames.length; i++) {
        console.log(filenames[i]);
    }
});

processId = process.getuid();
console.log(processId);

הדבר הכי חשוב פה הוא להסתכל איך הפעולה של ה-fs.readdir בנויה. אני מעביר לה שני ארגומנטים – הראשון הוא הפרמטר שהיא צריכה (באיזה נתיב לחפש) – בדיוק כמו הקוד הסינכרוני. השני הוא פונקציה אנונימית חביבה שמקבלת שני ארגומנטים גם היא: err (לתקלות) ו-filenames) שזו התוצאה. הפונקציה האנונימית מכילה את ההדפסה של שמות הקבצים. את ההדפסה של ProcessId אני מבצע כרגיל.

איך הפלט יראה לפי דעתכם? אותו הדבר?
בוודאי שלא! הוא יראה ככה:


$ nodejs test.js 
1000
test.js
test_sync.js

מה השינוי לעומת הפלט של הקוד הסינכרוני? שההדפסה של ה-ProcessId מתבצעת קודם! למה? איך זה יכול להיות? הרי ההדפסה הארורה מופיעה במורד הקוד! ההסבר הוא שכפי שהסברתי קודם לכן – מדובר בקוד א-סינכרוני. ה-callback של fs מופעל רק כשה-fs מסיימת לקרוא את מערכת הקבצים – עד אז הקוד ממשיך כרגיל ואין לנו תקיעות של המערכת.

אם זה נראה לכם מסובך או לא מובן מספיק, הייתי מציע לכם לבדוק את jQuery ו-AJAX – שם בדיוק זה אותו הדבר. אנו מבצעים פעולה (GET באמצעות AJAX לצורך העניין) ומבצעים callback רק כשהתוצאה מגיעה מהשרת, לא לפני. הסינטקס הוא אותו סינטקס.

המהפך מחשיבה של קוד סינכרוני לקוד אסינכרוני היא לא פשוטה, אנחנו נמשיך לדבר על קוד אסינכרוני בהמשך. מדובר באחד הדברים החשובים ביותר ב-Node.js.

כמה הערות חשובות לפני שממשיכים:

קולבקים הם לא הדרך היחידה לכתוב קוד א-סינכרוני בג'אווהסקריפט. יש לנו פרומיסים ויש לנו async await. בסדרת המדריכים הזו אני משתמש בקולבקים בלבד. אבל בספרים שלי "ללמוד ג'אווהסקריפט בעברית" וספר ההמשך "ללמוד Node.js בעברית" אני מלמד על שתי השיטות שלעיל. אם הספרים האלו מעניינים אתכם ואתם רוצים ללמוד ברצינות – נסו אותם.

 

 

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

נגישות טכנית – פודקאסט ומבוא

פרק בפודקאסטעל נגישות בעברית שצולל לכלים האוטומטיים ולפן המאד מאד טכני של הנגישות.

צילום מסך של סוואגר
יסודות בתכנות

openAPI

שימוש בתשתית הפופולרית למיפוי ותיעוד של API וגם הסבר בסיסי על מה זה API

גלילה לראש העמוד