nodejs הגדרת פונקציית השרת כ async
-
@רפאל אמר בnodejs הגדרת פונקציית השרת כ async:
לא ברור לאיזה משם אתה מתכווין, אני לא הצלחתי להבין (אני לא מבין אנגלית) משם פיתרון ללכידת שגיאות באקספרס כאשר אני העברתי לה async פונקציה, שהלקוח יקבל מיד תגובה בres ולא ימתין עד כלות.
אשמח אם תוכל לצוטט את החלק הנכון, (או לינק ישיר ע"י לחיצה ימנית על הטקסט בכרום)
תודה -
@חוקר טעיתי לחשוב שגירסה 5 (התומכת בטיפול בשגיאות עבור נקודות קצה\Middlewares המחזירות
Promise
ע"י קריאה ל()next
בצורה אוטומטית במקרה של כישלון או שגיאה) כבר שוחררה (באופן מוזר עדיין בשלב Alpha מאז 2014).מומלץ בנתיים להשתמש בספרייה Express-Async-Handler (כתחליף לשימוש רפטטיבי ב
try...catch
עבור כל אחת מנקודות הקצה\Middlewares המחזירותPromise
). -
זו הדרך שאני משתמש באקספרס, ולמיטב הבנתי זו דרך המלך:
צורה 1:
router.get("/", (req, res, next) => { getAllUsers() .then((users) => { res.status(200).json(users); }) .catch((err) => { const { code, message } = err; res.status(err.status).json({ code, message }); }); });
צורה 2:
router.get("/", async (req, res, next) => { try { const users = await getAllUsers(); res.status(200).json(users); } catch (err) { const { code, message } = err; res.status(err.status).json({ code, message }); } });
לגבי סנכרוניות - בקשה לשרת היא תמיד סינכרונית, ולכן אם אתה צריך לטעון מידע מרוחק (DB או כל דבר) כתשובה - אין שום סיבה או בעיה להשתמש בפונקציית הrout בפונקציה סינכרונית, זו לגמרי הדרך הנכונה. תחשוב: הלקוח שולח בקשה, שמגיעה לפונקציה שממתינה בכל מקרה לתשובה שלך, ולא סופרת כמה זמן לוקח עד שאתה עונה, ואם אתה צריך את "הזמן שלך" בשביל להביא את המידע, קח אותו. אין שום דרך להתחמק מהזה בתחביר כזה או אחר, אז כתוב את זה כראוי במקומו.
לגבי שגיאות - אין צורך להיעזר ב
middelware
בשביל טיפול בשגיאות. הדרך הנכונה והאמיתית היא טיפול בשגיאה לאורך שרשרת הקריאות, כל פעם טיפול מקומי, והעברת השגיאה הלאה במידת הצורך, עד זריקתה למשתמש אם לא נמצא פתרון קודם.יש אפשרות להוסיף פונקציה אחידה לטיפול בשגיאות שתקרא רק במקרה (הלא רצוי) של שגיאה שלא נלכדה במקום אחר, כדי לא להקריס את השרת. בצורה כזו:
process.on("uncaughtException", (err) => { console.error("There was an uncaught error", err); // process.exit(1); //mandatory (as per the Node.js docs) });
זה ימנע מהשרת לקרוס, אבל זה לא יחזיר תשובה למשתמש, ובכלל זה לא בריא. צריך להשתמש בזה בתבונה. בגדול אם הגעת לשם קרוב לודאי שמשהו בקוד שלך לא תקין. במצב פרודקשן הייתי שוקל לשלוח התראה למתכנת במייל מתוך הפונקציה עם פרטי השגיאה - במידה והגענו עד כאן.
-
@davidnead דרך המלך שלך היא טיפול בכל שגיאה, ולא לכידת שגיאות גלובלית (אתה בעצם חייב להתייחס בכל מקום לכל שגיאה אפשרית). ברור ש"אין צורך להיעזר בmiddelware" אם אתה מוותר על טיפול במקום אחד בשגיאות, רק שהטיפול בשגיאות שלך מפוזר על פני מקומות וגם הקוד שלך די גודל.
דרך המלך היא טיפול במקום אחד לכל השגיאות הלא צפויות בלי לכתוב טריי בשום מקום, וטיפול מקומי רק אם נדרשת התייחסות מקומית (למשל נסיון באופן אחר).
כמו ש@רפאל אמר אם רוצים להשיג כזו התנהגות יש להשתמש בגירסה 5 או לעשות טריי עם Next(err) בכל מקום.
נ.ב. כתבת בטעות סינכרונית התכוונת אסינכרונית.
-
@dovid אמר בnodejs הגדרת פונקציית השרת כ async:
@davidnead דרך המלך שלך היא טיפול בכל שגיאה, ולא לכידת שגיאות גלובלית (אתה בעצם חייב להתייחס בכל מקום לכל שגיאה אפשרית). ברור ש"אין צורך להיעזר בmiddelware" אם אתה מוותר על טיפול במקום אחד בשגיאות, רק שהטיפול בשגיאות שלך מפוזר על פני מקומות וגם הקוד שלך די גודל.
דרך המלך היא טיפול במקום אחד לכל השגיאות הלא צפויות בלי לכתוב טריי בשום מקום, וטיפול מקומי רק אם נדרשת התייחסות מקומית (למשל נסיון באופן אחר).
כמו ש@רפאל אמר אם רוצים להשיג כזו התנהגות יש להשתמש בגירסה 5 או לעשות טריי עם Next(err) בכל מקום.
נ.ב. כתבת בטעות סינכרונית התכוונת אסינכרונית.
סינכרונית - אתה בטוח שטעיתי? הasyc מבלבל, אבל תכל'ס המשמעות של קוד סינכרוני הוא קוד שלא ממתין אלא מתבצע בו זמנית. הasync מאלץ את הסקופ הספציפי של הפונקציה להתנהג פנימית כמו קוד אסינכרוני.
לגוף הענין - כמו שכתבת בעצמך, יש הבדל בין שגיאות צפויות ללא צפויות. גם אני הזכרתי את זה. אבל אתה אמור להשתדל לצפות כל שגיאה ולהתייחס אליה, כי היחס (הטיפול, והרבה פעמים גם התגובה הסופית למשתמש) משתנה בין השגיאות השונות. זה אכן מאריך את הקוד, אבל יותר נכון.
אם אתה בונה את הקוד שלך ואת הAPI בצורה מאוד מסודרת, עם סגנון תגובה אחיד לכל השגיאות, אתה יכול לחסוך חלק מזה ולהסתפק במטפלים גלובליים. זה קשה, ולא תמיד ישים.
צורה מסודרת אני מתכוון שיש לך איזו מחלקה לטיפול בשגיאות API, שמכירה את כל השגיאות האפשריות שיכולות להגיע ויודעת להתייחס אליהם בהתאם, ושאתה דואג שתמיד כל שגיאה תגיע אליה, והכי בעיתי - להבדיל בין שגיאה מקונטרולר לשגיאה של ראוט. כי בדרך כלל הראוט קורא לפונקציה שנמצאת בקונטרולר (או מקום אחר) ואינה משתמש בהכרח להחזרת ערך לראוט, ולכן אתה צריך לטפל בתוכה בשגיאה באופן שיתאים לכל מי שקורא לה. אם תיתן לשגיאה להיזרק מתוך הפונקציה על סמך מטפל גלובלי היא עשויה לחטוא לתפקידה כיחידה עצמאית שאמורה להחזיר ערך - שמי שקרא לה אמור לדעת לטפל בו. -
@davidnead בקשר לשגיאות בא נסכם שאנחנו מסכימים. רק שהדיון פה וגם ב99% מהמושג טיפול בשגיאות בסביבה אינטרנטית מדברים על שגיאות שלא תלויות בזרימת היישום בכלל.
שגיאות אלו שמקורם בגורמים חיצוניים או בקלט שגוי (בקיצור IO) הם אין סוף אפשרויות ואין אפשרות וגם היגיון לצפות להם ולטפל בהם אינבדואלית ברוב המקרים.דוגמאות לשגיאות צפויות: שם משתמש וסיסמה לא תקינים, העלאת קובץ בפורמט הלא נכון, שם קטגוריה לא קיימת, השרת במצב תחזוקה וכדומה.
שגיאות לא צפויות: מסד נתונים לא מגיב, מערכת קבצים לא פועלת (למשל דיסק מלא). וכמובן כמובן, שגיאה לוגית בקוד. כמה אופייני, אדם לא צופה איפה הוא יטעה ומה תהיה הטעות ואין לו נסוח אינבדואלי לטעות שהוא עדיין לא הכיר בה.@davidnead אמר בnodejs הגדרת פונקציית השרת כ async:
סינכרונית - אתה בטוח שטעיתי? הasyc מבלבל, אבל תכל'ס המשמעות של קוד סינכרוני הוא קוד שלא ממתין אלא מתבצע בו זמנית. הasync מאלץ את הסקופ הספציפי של הפונקציה להתנהג פנימית כמו קוד אסינכרוני.
ממתין = סינכרוני. בפונקציה רגילה אתה מקבל תוצאה אחרי שהיא נגמרה, כלומר קודם הפונקציה, אח"כ הערך החוזר.
בפונקציה אסינכרונית - הערך חוזר מייד (פרומייס), הפונקציה נגמרת בהמשך.
כלומר אין סינכרוניות של קודם הפונקציה ואז הערך החוזר והקוד הקורא ממשיך, אלא תיכף הערך חוזר והקוד הקורא יכול להמשיך לפי החלטתו עוד בטרם הפונקציה השלימה את פעולתה. -
@dovid אמר בnodejs הגדרת פונקציית השרת כ async:
@davidnead בקשר לשגיאות בא נסכם שאנחנו מסכימים. רק שהדיון פה וגם ב99% מהמושג טיפול בשגיאות בסביבה אינטרנטית מדברים על שגיאות שלא תלויות בזרימת היישום בכלל.
אם אמרת שאנו מסיכמים, איבדתי את המוטיבציה להתווכח נאלץ לעצור את הדיון.
-
אישית כן יחכים אותי ריבוי הדעות כאן.
הרבה מדי אני נתקל במצב שבו בתגובה לבקשה בודדת, צריך לבצע שרשרת של פעולות.
ובכל שלב עלולה להיווצר שגיאה, ורוצים להחזיר מידע מדויק מהי השגיאה, או סטטוס באיזה מצב אנחנו כעת.
אז הדרכים שאני מכיר זה או לשמור מידע בנפרד, ואז יש יכולת לשחזר בכל מצב את הנתונים.
זה רלוונטי רק במקרים שהבקשות חוזרות על עצמן, ויבוצעו שוב בהמשך.
אם לא, או שכל בקשה עומדת בפני עצמה, או שאין סיבה לשמור נתונים,
אז או לעטוף כל שלב בtry..catch
או להחזיק אובייקט כללי לסקופ הזה, ולדחוף אליו כל נתון אפשרי כדי שיהיה איך להוציא משם שגיאות.
השאלה מהי הדרך הכי טובה\נכונה. -
הנושא המקורי פה הוא "טיפול בשגיאות בשרת אינטרנט"
@davidnead עבר לנושא "מתי לטפל בשגיאות באופן ספציפי ומתי גלובלית"
ו@5566brs בעקבותיו עבר לתת נושא בטיפול ספציפי "איך לטפל בשגיאות של פרוצדורה מרובת שלבים"...
@5566brs בהרבה מקרים ניתן להבחין בין השלבים ע"י סוג השגיאה (conditional catch-blocks).
בשביל "להצמיד" מידע על השגיאה, כדאי להעביר את הפעולה לפונקציה, שם לעטוף בטריי ובמקרה שגיאה לזרוק (throw) שמה את השגיאה עם המידע הרלוונטי.
אני לא יודע באמת מה דרך המלך בכזה מקרה (בשפות כמו C# וג'אוה אז משתמשים אז בפילטר הנ"ל, כי השגיאות מאוד מפרטים על השגיאה).