nodejs הגדרת פונקציית השרת כ async
-
מממ אם אני מבין אותך טוב, אז הפונקציה שאתה מעביר לapp.get משמשת לכל הפעולות.
ואתה שואל אם זה בעיה לסמן אותה כasync וככה גלובלית כל הקוד שלך הופך להיות async.אם זו השאלה, אז בטח שזה טוב, אדרבא הדרך הקודמת שלך הייתה משונה.
סימון פונקציה כasync לא עושה אותה נכה אלא רק גורמת לשינוי איך שהיא עובדת - הערך חוזר ממנה ישירות וכל הawait שבתוכה הופכים להיות פרומייז. -
@dovid אמר בnodejs הגדרת פונקציית השרת כ async:
אם זו השאלה, אז בטח שזה טוב, אדרבא הדרך הקודמת שלך הייתה משונה.
זה הגיע מחוסר ידיעה..
כשהתחלתי לכתוב nodejs (בזכותך..) לפני 3 שנים בערך, לא ידעתי שניתן לעשות זאת, והתמודדתי בשינויים מPHP לnodejs, ורק זה היה הפיתרון שמצאתי אז..
מאז התקדמתי המון ב"ה.. אבל לא היה לי צורך ממשי לשנות, לאחרונה כבר תקופה שחשבתי לשנות זאת, אבל הסתפקתי, כעת נוצר לי צורך חוזר, ואמרתי בא נברר את זה.
למעשה, תוך כדי, לאחר שכתבתי את הפוסט כאן ניסיתי לחפש בגוגל ומצאתי פוסט בנושא, מבחינת הטיפול בשגיאות, ואני מנסה להבין את זה איפה זה ישנה לי.
https://stackoverflow.com/questions/44813401/passing-in-async-functions-to-node-js-express-js-router/67689269#67689269 -
@חוקר אמר בnodejs הגדרת פונקציית השרת כ async:
מבחינת הטיפול בשגיאות
אני חושב שזה לא אמור כ"כ להפריע לי, כי אני כמעט לא נתקלתי בשגיאות שנזרקות לדפדפן, כמעט או כל השגיאות שיכולות להיות אני מטפל בהם מקומית עם הודעות שגיאה מתבקשות
לדוגמא:..catch(error => { console.error(error); return {status : 'error', message : 'תקלה בסליקת האשראי'}; });
וא"כ נראה שזה לא אמור להפריע לי.
האם הבנתי נכון? -
@חוקר אמר בnodejs הגדרת פונקציית השרת כ async:
למעשה, תוך כדי, לאחר שכתבתי את הפוסט כאן ניסיתי לחפש בגוגל ומצאתי פוסט בנושא, מבחינת הטיפול בשגיאות, ואני מנסה להבין את זה איפה זה ישנה לי.
https://stackoverflow.com/questions/44813401/passing-in-async-functions-to-node-js-express-js-router/67689269#67689269ניסיתי את הפתרון שהוא מציע בסוף הפוסט, וזה נראה בסדר גמור
app.get('/error', async (req, res, next) => { try { throw new Error('my error' res.send('never returned') } catch(error) { next(error); } })
השגיאות מטופלות כראוי.
-
@רפאל אמר ב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# וג'אוה אז משתמשים אז בפילטר הנ"ל, כי השגיאות מאוד מפרטים על השגיאה).