בהנחה שיש למשתמש דף עם טופס, בטופס המשתמה יכול להוסיף אין סוף תיבות טקסט ו/או לעדכן קיימת.
לאחר שהוא סיים, ללחץ על שמור ולשלוח את כל המידע לשרת.
זה שם אותנו במצב שהשרת שלנו קיבל מערך של אובייקטים שחלקם מחזיקים ב-ID (כל השורות שהגיעו מהשרת) ואותם אנחנו צריכים לעדכן.
חוץ מהם, יגיעו גם אובייקטים ללא ID (החדשים שהמשתמש יצר) ואותם רוצים להוסיף לבסיס נתונים.
זה אומר שאנחנו צריכים לרוץ בלולאה על המערך ולשמור או לעדכן את השורות ובסוף לשלוח אם התהליך הסתיים בהצלחה או לא.
למי שיצא לעבוד בעבר עם NODEJS+MONGODB שם לב שיש insertMany ויש updateMany.
לצערנו הם לא עושים פעולות דומות:
- insertMany – יכול לקחת מערך של אובייקטים ולשמור אותם בפעולה אחת בבסיס הנתונים.
- updateMany – מעדכן את אותו ערך לכל הרשומות בבסיס הנתונים שעונות פילטר שניתן לו.
אם נשתמש ב-updateOne ונרוץ בלולאה, לא נדע מתי להחזיר תשובה חזרה כשהפעולה בוצעה.
שמירה ב-DB היא פעולה async והלולאה שלנו לא, לכן אם נרוץ בלולאה זה לא יעבוד לנו כמו שאנחנו מצפים,
בסופו של דבר יחזיר למשתמש תשובה בלי בדיקה של הנתונים לשגיאה בזמן פעולה.
פיתרון שמצאתי לבעיה הזאת נראה כך:
exports.updateExternalLinks = async (req, res, next) => {
Promise.all(req.body.links.map(async (item) => {
if (item.id) {
await ExternalLinks.updateOne({ _id: item.id }, item);
}
else {
item.creator = req.userData.userId;
await ExternalLinks.insertMany(item);
}
})).then(() => {
res.status(200).json({
message: 'Update completed'
});
}).catch(() => {
res.status(500).json({
message: 'Update failed'
});
});
}- שורה 1 – תמיד רעיון טוב לעבוד async כדי לא לתפוס משאבים אלא להשתמש בהם רק שצריך.
- שורה 2 – זה מה שעושה את הקסם שאנחנו צריכים, promise.all ממתין לכל התשובות ומנסה להערך האם הפעולה עברה תקין או שחלק מהתשובות חזרו עם שגיאה.
במידה שאפילו אחת חזרה עם שגיאה, הוא מוציא תשובה של שגיאה על כל הפעולה כך אנחנו יודעים איזו תשובה להחזיר.
בנוסף, ניתן לראות שה-map מפעיל פונקציות שהם בהגדרה async, כדי שהם ישלחו לבסיס הנתונים ויטופלו בתורם ואנחנו נוכל להשתמש ב-await כדי להמתין לתשובה מהבקשה.
- שורה 3 – בשורה זו בודקים ומבדילים בין השורות שצריך לעדכן ואלו שצריך להוסיף לבסיס הנתונים.
הבדיקה היא על הזיהוי של האובייקט, כך שאם יש זיהוי זה אומר שבהכרח הוא הגיע וקיים ב-DB ואם הזיהוי ריק אז הוא חדש ולא הגיע מה-DB.
- שורה 7 – כחלק מהמודל של האובייקט, הוגדר creator (אפשר להשתמש בכל שם שרוצים) והוא מתפקד כזיהוי ושיוך למשתמש הספציפי. אם נשווה אותו ל-SQL אז הוא FK, זאת אומרת, שהוא מחזיק את ה-ID של המשתמש (PK).
- שורה 10 ועד הסוף – מופעל לאחר שה-promise מוציא את הסטטוס, במידה שהסטטוס שגיאה אז אנחנו שולחים למשתמש סטטוס 500 והודעה שהעדכון נכשל, אחרת אנחנו מחזירים תשובה שהעדכון הצליח.





