js throw false
-
@חוקר אמר בjs throw false:
ואני בעוניי לא מבין מה הבעיה להכניס כאן את שורת הקוד, היכן זה יוכל להפריע לי?
@dovid אומר שיש כאן סוגיא חינוכית השקפתית עם השפעה לטווח הרחוק, הוא עומד על האכסדרה ויש לו סמכות להזהיר את ההולכים בשבילי הגן, אתה רשאי להאמין או לא להאמין לו, אבל זה לא רלוונטי לנסות להבין איפה הבעיה כאן בקוד שלך היום.
האתגר שלך מעניין אותי, אם תרצה, צור איתי קשר (בלי התחייבות דו צידית) במייל -
@יוסף-בן-שמעון אם תצליח למצוא איזה פתרון יצירתי אשמח אם תעדכן אותנו
אני חושב על סוג של state machine. משהו בכיוון שלswitch
ארוך ולהגדיר לכל שלב של השיחה state.router.get('/test', function (req, res) { let state = 'initial'; let infoNeeded = { message: null, varName: null }; function read (varName, message) { if (req.query[varName]) { state = `got_${varName}`; return req.query[varName]; } else { infoNeeded = { message, varName }; state = 'needMoreInfo'; } } function requestInfo (infoNeeded) { res.end(`read=${message}=${varName}`); } while (1) { switch (state) { case 'needMoreInfo': return requestInfo(infoNeeded); case 'initial': var id = read('id', 'הקש תעודת זהות'); break; case 'got_id': var name = read('name', 'f-הקלט את שמך'); case 'got_name': var status = read('status', 't-בחר את הסטטוס האישי, לבחור הקש אחד לאברך הקש שתיים לתתלמיד חיידר הקש שלוש') break; case 'got_status': if (status === '1') { // ... } else if (status === 2) { // ... } default: throw new Error('Unknown state!') } } }
אבל ברור שזה צורת חשיבה אחרת מאשר הפתרון של זריקת exception. לקבל קוד קל שעובד בזורם בדיוק בדרך שהראש של @חוקר זורם יהיה מאתגר...
פתרון נוסף הוא הדרך של @MusiCode דהיינו לעשות שפונקציית ה-read
יהיהasync
ואם המשתנה לא קיים זה יבקש אותו מימות המשיח ויעצור את הפונקציה עד לקריאה הבאה של ימות המשיח. אבל משום מה @חוקר ממאן ללכת בדרך זו. (או משהו דומה - אם כי קצת טריקי - שאני הצעתי פעם בשימוש עם generator-ים)@חוקר, חבל שאתה לא הולך בדרך של @MusiCode, אני אוהב אותה...
בעצם ניתן לקחת את המהלך של state machine שלב קדימה ולחסוך את ה-boilerplate של ה-
while
וה-switch
על ידי כתיבת פונקציה שיקרא אוטומטית לשלב הבא של השיחה על סמך שם המשתנה שהתקבל. והמתכנת יכתוב רק פונקציות עם שמות שנחצבות מתוך שם המשתנה האחרון שהתקבלה בשיחה. נשאיר את זה לשיעורי בית... -
המחשבה שהסיטואציה של ימות המשיח מכניסה אותך למצב ששפת JS לא נותנת פתרון אלגנטי, שגויה לחלוטין. המקרה הזה לא נדיר והגיוני בהמון מצבים.
האפשרות לבדוק רק בסוף אם כל הערכים הגיעו היא ודאי לא אופציה, כפי שאמרת זה לא יעיל ויביא שגיאות.
האפשרות לכתוב שוב ושוב return בפונקציה הקוראת בהתאם לערך החוזר היא בהחלט גם "עבירה", אבל היא עבירה הרבה יותר קלה, למרות שאתה ממש מתנגד לעניין.
האפשרות הנכונה זה לכתוב קוד טוב...
דוגמה שזורמת עם הדרך שלך:app.get('/xyz', function(req, res){ var data = {}; if(!read(req, res, data, 'f-הקלט את שמך', 'name', VOICE)) return; if(!read(req, res, data, 't-בחר את הסטטוס האישי, לבחור הקש אחד לאברך הקש שתיים לתתלמיד חיידר הקש שלוש', 'status', MENU + '12')) return; if (data[status] === '1'){ if(!read(req, res, data, 't-הקלט את שם הישיבה ולסיום הקש סולמית', 'yeshiva', VOICE)) return; database.insertSQL({'name' : name,'yeshiva' : yeshiva}, 'bachurim').then(id => { say('t-נרשמת בהצלחה המספר האישי שלך הינו.n-' + id); }) } ... } function read(req, res, data ...){ if(data[name] = req.query[name]) return true; else ... }
אבל הרבה יותר טוב היה לממש משהו גנרי לזרימה הזו. אתה טענת באשכול ההוא וגם טענו אחריך בנושא מיוחד שפתחתי עבור זה שזה מידי מסובך. כלומר אתם עסוקים מידי מכדי לחסוך זמן וכח....
הנה דוגמה למשהו גנרי:
app.get('/xyz', function (req, res) { var flow = { name: { next: () => ["status"], askUser: `t-בחר את הסטטוס האישי, לבחור הקש אחד לאברך הקש שתיים לתתלמיד חיידר הקש שלוש` /* , ...*/ }, status: { askUser: `t-הקלט את שם הישיבה ולסיום הקש סולמית`, /* , ... ,*/ next: function (val) { if (val == "1") return "yeshiva"; if (val == "2") return "isuk"; if (val == "3") return "..."; } }, yeshiva: { next: null, askUser: `t-הקלט את שם הישיבה ולסיום הקש סולמית` }, isuk: { next: (val) => ({ 1: "kolel", 2: "work" }[val]), askUser: `t-אברך כולל הקש אחד, נהנה מיגיע כפיו הקש שתיים` }, kolel: { next: null, askUser: `t-הקלט את שם הכולל ולסיום סולמית` }, work: { next: null, askUser: `t-הקלט את שם מקום העבודה` }, }; var data = req.query || {}; if (!proccessStep("name")) //all data ready? return false; //... //work with data if(data[status] == "1"){ database.insertSQL({ 'name': name, 'yeshiva': yeshiva }, 'bachurim').then(id => { say('t-נרשמת בהצלחה המספר האישי שלך הינו.n-' + id); }) } //... //... function proccessStep(key) { if (!data[key]) { //res.end() ... return false; } var next = flow[key].next(data[key]); if (next) return proccessStep(next) else return true; } });
בקוד הזה אתה מעביר לפוקנציה רקורסיבית את הדאגה שכל המידע יתקבל, הזרימה של קבלת המידע מתבצעת בהתאם לאובייקט דקלרטיבי קל לתחזוקה ושינויים.
(הרעיון שהפוקנציה היא בפנים הפונקציה ולא בחוץ היא פרקטיקה נכונה כאשר הפונקציה ייעודית לפונקציה זו או שהיא תלויה בה במידי תלויות, זה עדיף מלהעביר הרבה פרמטרים).האם הקוד הזה טוב? לא.
יש בו המון מה לשפר, הflow לא חד בתכליתו כי הוא כאילו רק לאסוף מידע אבל בתכלס כל הפעולה זה איסוף מידע אז שגם ישמור בnext האחרון בdb. יש פה עוד הרבה מה להשחיז. אבל תרחמו על עצמכם, תחשבו. -
אני כבר כותב את התגובה במשך שעה עם הפרעות באמצע, ובינתיים אני רואה ש@yossiz לא טמן את ידו בצלחת. אני רוצה להרויח מעבר לפתרון הנקודתי שינוי אסטרטגיה, ולא כל פעם לכבוש את המכשול התורן.
@yossiz אמר בjs throw false:
אתה הבעל המחבר של השיטה... אני מוכרח לומר שאני לא שוכח את ההברקה וכבר עשיתי בה שימוש בפרודוקשיין. אבל לדעתי פה זה לא נצרך ומסרבל את פעילות האפליקציה.
-
@yossiz אמר בjs throw false:
פתרון נוסף הוא הדרך של @MusiCode דהיינו לעשות שפונקציית ה-read יהיה async ואם המשתנה לא קיים זה יבקש אותו מימות המשיח ויעצור את הפונקציה עד לקריאה הבאה של ימות המשי
מה קורה אם אתה רוצה לבצע שינויים בקוד כשיש מאזינים על הקו?
אם זה כל פעם יוצר מופע חדש, אין לך בעיה שהשרת יהיה למטה לכמה שניות
אבל אם זה זה מופע אחד ארוך, אתה תפיל ללקוח את כל התהליך. -
@yossiz
איך הספקתי לשכוח מהקטע הזה?
אז זה אומר שלא לשמור נתונים בזיכרון ,אלא לשמור הכל בדיסק (כמו שחוקר עושה)
ומרוויחים בעיקר מבנה תקין של הקוד.
ובכל שלב הוא בודק איזה משתנים הוא קיבל, ואם הוא קיבל כבר 8 משתנים, הוא קופץ קדימה?
או שלא הבנתי איך הספריה עובדת? -
אז ככה.
לא הביישן למד..
אני שמח לבשר לכם שמצאתי בעיה למה לא טוב להשתמש בטכניקה הנ"ל שהמצאתי.
וכמובן @dovid ושאר החברים שלא תמכו ברעיון שלי, צדקו שלא חכם להשתמש בזה.
לאחרונה ראיתי הרבה פעמים שאני מקבל בלוג, שגיאה עם ערך false.
לא הבנתי מאיפה השגיאה ולמה, אבל זה שגיאה שמילאה את הלוגים די הרבה.
היות ויש לי המון שורות קוד שפולטות שגיאה במידה ויש שגיאה, ולא יכולתי לנחש מהיכן השגיאה, לכן חיפשתי משהו ברשת שמאפשר לקבל את השורה שפולטת את השגיאה.
מצאתי את https://stackoverflow.com/a/48566862 ויישמתי אותו, ועל פי זה הגעתי לשורה שנמצא בתוךcatch
של פרומיס/
אך מה שהיה מוזר, שמדובר בפרומיס שהסתיים ללא בעיות, והכל פעל כשורה, ובטלפון לא הורגש שום בעיה.
ולכן התפלאתי מה קורה, ולמה רק לאחרונה זה התחיל לקרוא.
עד שנפל לי האסימון, מדובר במקומות שבסיום הthen
יש קריאה ל read שהיה מורכב מבקשה בלבד, כי הטיפול בערך שהתקבל היה ממוקם בקוד לפני זה, (שוב, בגלל המורכבות בעבודה מול ימות המשיח), ולכן נוצר מצב שזה נשאר בקטע שלres.end('read=הקש זהות=id'); throw false;
ויצר מצב שהמטפל שגיאות של הפרומיז הבין שיש שגיאה, ולכן הקטע קוד שב catch רץ, אך בגלל והפקודה הייתה להדפיס את השגיאה, ובאמת אין שגיאה כי לא היה קריאה ל resolve, לכן זה פלט false.
מי שהבין שירים אצבע...
בכל מקרה מתברר שזה לא דרך יעילה.
אז אולי אהיה מוכרח להתרכז כבר בקוד ש @dovid כתב.
או להישאר עם השיטה הפרימיטיבית שלif (typeof yeshiva !== 'string'){ return false; }