איך עובד זרמים ב-nodejs
-
תריץ את הקוד הזה ותעקוב אחרי הקונסול:
var i = 0; var obj = { on: event => console.log("ON", event), once: event => console.log("ONCE", event), emit: event => console.log("EMIT", event), write: data => console.log("WRITE", i++, data), end: () => console.log("END"), }; fs.createReadStream('1.txt', 'utf8').pipe(obj);
-
@מנצפך אמר באיך עובד זרמים ב-nodejs:
@אהרן אמר באיך עובד זרמים ב-nodejs:
הארגומנט הוא פונקציה שלתוכו pipe מזריק את הדאטא? הרי res אינו פונקציה?!
אני מתאר לעצמי שברור לך שב- JS אובייקט ופונקציה חד הם.
NO!
-
@יוסף-בן-שמעון אמר באיך עובד זרמים ב-nodejs:
תריץ את הקוד הזה ותעקוב אחרי הקונסול:
var i = 0; var obj = { on: event => console.log("ON", event), once: event => console.log("ONCE", event), emit: event => console.log("EMIT", event), write: data => console.log("WRITE", i++, data), end: () => console.log("END"), }; fs.createReadStream('1.txt', 'utf8').pipe(obj);
מושלם!
אז אני מבין שהדאטא מוזרם לתוך פונקצית res.write ובסוף הכל נשלח בבת אחת והחיבור נסגר באמצעות res.end, כפי שרואים בדוגמא הבאהapp.get('/test', (req, res) => { res.write('OK1'); setTimeout(()=>res.write('OK2'),1500); setTimeout(()=>res.end('OK END'),2500); }) setTimeout(()=>{ request({url: url}, function (error, response, body) { console.log(body); }); } ,2.5*1000);
אז מדוע בדוגמא הזאת
fs.createReadStream(path).pipe(res)
הדאטא מתחיל להישלם מיד עם ההזרמה הראשונה?
-
-
@dovid
אז מדוע בקוד הזה כל הדאטה נשלח בב"א?app.get('/test', (req, res) => { res.write('OK1'); setTimeout(()=>res.write('OK2'),1500); setTimeout(()=>res.end('OK END'),2500); }) setTimeout(()=>{ request({url: url}, function (error, response, body) { console.log(body); }); } ,2.5*1000);
-
על השאלה הראשונה (לא הבנתי בכלל את דוגמת הקוד אבל אני מניח שזה טסט שמוכיח את מה שאתה טוען), התשובה כנראה נעוצה בבאפר. לכל סטרים יש יכולת לאגור כמות מסויימת לפני הכתיבה מטעמי יעילות (למשל ייתכנו הבלים בן התקנים שלקרוא מהתקן אחד יעיל לקרוא ביט ביט ולכתוב לשני כדאי לעשות בגושים של 10KB).
בקשר לשאלה השניה, אנא קרא את תשובתי הראשונה באשכול. יכולים להיות עשר הזרמות משורשרות, הכתיבה בראשון גוררת כתיבה בכולם. כל אחד מתי שהוא מקבל chunk אחראי לכתוב את זה לסטרים שהוא קיבל כפרמטר בpipe.
-
@אהרן אמר באיך עובד זרמים ב-nodejs:
שאלה נוספת
encodeStream.pipe(zlibStream).pipe(res);אני מבין שה-pipe השני מזרים את הדאטא הערוך ע"י zlibStream, איפה הוא נשמר בין 2 ההזרמות?
אני חושב שרק הפונקציה pipe מזרימה stream.
write ו - end כותבים בצורה רגילה. -
@אהרן אמר באיך עובד זרמים ב-nodejs:
@dovid
אז מדוע בקוד הזה כל הדאטה נשלח בב"א?app.get('/test', (req, res) => { res.write('OK1'); setTimeout(()=>res.write('OK2'),1500); setTimeout(()=>res.end('OK END'),2500); }) setTimeout(()=>{ request({url: url}, function (error, response, body) { console.log(body); }); } ,2.5*1000);
לא ברור לגמרי מה התכוונת בקוד הזה, אבל אם אני מבין נכון בפונקציה request אתה שולח לעצמך בקשה ומדפיס את התשובה לקונסול, אם כך זה ברור למה אתה רואה הכל מודפס בבת אחת, כי השתמשת ב callback במקום ב streaming, אז זה מחכה שכל התשובה תגיע ואחר כך קורא לפונקציה.
אם אתה רוצה לראות מימוש של streaming תכתוב כךrequest(url).pipe(obj)
-
@dovid אמר באיך עובד זרמים ב-nodejs:
בקשר לשאלה השניה, אנא קרא את תשובתי הראשונה באשכול.
תודה על המחמאה. באמת.
@dovid אמר באיך עובד זרמים ב-nodejs:
הכתיבה בראשון גוררת כתיבה בכולם
גם פונקציה ראשונה באפליקציה 'גוררת' את כל הפונקציות שאחריה, זה עדיין לא מסביר איך.
לעצם הענין, ככל שאני מבין, מופע זרם מכיל רק מערך, המתודות יורשות, חתיכות ההזרמה פשוט מצטברים במערך עד שהם יכולים להשתחרר.
-
@אהרן לא הבנתי מה המחמאה, או במידה וזה אירוני, ממה העלבון.
כיון שאני משוכנע שאם היית קורא את מה שכתבתי ביתר אמון ורצון להבין היית כבר יודע יותר, אני מרשה לעצמי להיות מתוסכל ולהביע זאת.
דחית מה שאמרתי בלי לקרוא ברצינות את תשובתי הראשונה (אולי זה היה מעליב ההפניה לשמה, אבל כתבתי את זה נטו בשביל לגרום לך לקרוא יותר) תוך היצמדות לניסוח (אדרבא, בא תסביר משהו שיבינו אותך בקלות בנושאים כאלו), גם מוסיפה לי מורת רוח. בשביל לחסוך גלילה אחורה:הStream של הקובץ מספק את המתודה pipe ושמה יש קוד פשוט שמקבל ארגומנט מסוג Stream אחר. והוא דואג על כל פיסת מידע שהוא מביא, לעשות write בזרם שהובא לו כפרמטר.
אולי לא הייתי ברור במילים ש"הוא מביא" (לא ידעתי בכלל איך זה ממומש עם הevent כמו שהסביר @יוסף-בן-שמעון, כי אני מכיר את הרעיון של סטרים התיאורטי לא דוקא את מימושו בנוד), אבל ודאי שיש פה חומר קריאה ושהוא נכון. וודאי שמי שקורא בעיון את מה שכתוב פה לא יחשוב שהחומר (של הchunk הקודם) נשמר באיזה מקום.
לעצם הענין, ככל שאני מבין, מופע זרם מכיל רק מערך, המתודות יורשות, חתיכות ההזרמה פשוט מצטברים במערך עד שהם יכולים להשתחרר.
אתה טועה, כל הרעיון של סטרים הוא שאיננו שומר כלום בשום מקום, הוא נטו צינור.
אפשר לתאר שרשור סטרימים ע"י סדרה של צינורות קטנים שמחברים אחד לשני, ובידוק לכן קוראים לזה pipe ולכן גם בחרו בלינוקס את תו הצינור בשביל הפעולה הזו. -
@dovid אמר באיך עובד זרמים ב-nodejs:
כל הרעיון של סטרים הוא שאיננו שומר כלום בשום מקום, הוא נטו צינור.
אפשר לתאר שרשור סטרימים ע"י סדרה של צינורות קטנים שמחברים אחד לשני, ובידוק לכן קוראים לזה pipe ולכן גם בחרו בלינוקס את תו הצינור בשביל הפעולה הזו.
המודל request מאפשר לקבל את המידע גם בסטרימינג וגם לקבל אותו מלא עם callback, זה אומר שאם אתה בוחר ב callback חוץ מהסטרימינג את גם טוען לזיכרון את כל המידע.
כאן הוא בודק אם העבירו ארגומנט callback אז הוא כן טוען למערך את כל ה chunks