שימוש ב-MongoDB בנוד
-
אני רוצה לעשות מודול שיחזיר לי מופע של MongoClient.db שאוכל להשתמש בו מיד.
אופן השימוש יהיה כך:db = require('./db') db.collection('xyz').insert({1:2});
אך נראה שבלתי אפשרי לייצר דבר כזה עם הקליינט הרשמי של מונגו עבור נוד. האמנם כן?
הבעיה היא שאי אפשר לקבל מופע של ה-db בלי להתחבר קודם, והחיבור הוא אסינכרוני.נסיון נאיבי שלא עובד:
const MongoClient = require('mongodb').MongoClient; const url = 'mongodb://localhost:27017'; const dbName = 'dbname'; const client = new MongoClient(url); let db; client.connect() .then(client => { console.log('Connected!'); db = client.db(dbName); }) .catch(err => { console.log('Failed to connect:', err); }); module.exports = db;
-
הפיתרון הוא לכאורה להחזיר אובייקט שיעטוף את ה-
db
. כל פונקציה שנקרא על העטיפה יעשה קודםawait
לאובייקט ה-db
האמיתי ואז יעביר את הפונקציה הלאה לאובייקט האמיתי.האם יש דרך לעשות עטיפה כזאת בלי יותר מדי boilerplate? פשוט להגיד ל-JS שכל פונקציה שאני יקרא על האובייקט לא משנה מה השם שלו יעבור דרך קוד העטיפה?
-
ראשית אני לא כ"כ משתמש בנוד, אז אני לא יודע דברים בסיסיים.
אני מבין ראשית כל שכל השאלה נשענת על כך שא"א לעשות await require.בפתרון הנאיבי שלך הexport קורה לפני החיבור, ממילא הexport מוציא null.
אם ניתן לו אובייקט לכאורה תוכל למלא אותו בהמשך, כלומר ככה גם לא יעבוד?const MongoClient = require('mongodb').MongoClient; const url = 'mongodb://localhost:27017'; const dbName = 'dbname'; const client = new MongoClient(url); let container = {}; client.connect() .then(client => { console.log('Connected!'); container.db = client.db(dbName); }) .catch(err => { console.log('Failed to connect:', err); }); module.exports = container;
db = require('./db').db;
סתם ככה, תמיד שכשיש לך בjs פונקציה אחת שהיא אסינכרונית עושה רושם שהיא תוקעת את כל הסטאק שקורא לה, כשהאמת הפוכה, היא היחידה שמתנהגת טוב..
-
@dovid אמר בשימוש ב-MongoDB בנוד:
אני מבין ראשית כל שכל השאלה נשענת על כך שא"א לעשות await require.
אפשר, אבל צריך לעטוף אותו בפונקציה בגלל שלא קיים toplevel await (אולי קיים בצורה נסיונית, לא בדקתי).
בפתרון הנאיבי שלך הexport קורה לפני החיבור, ממילא הexport מוציא null.
בדיוק
אם ניתן לו אובייקט לכאורה תוכל למלא אותו בהמשך, כלומר ככה גם לא יעבוד?
כן, אבל לא אוכל להשתמש בו בצורה עיוורת כי לא אוכל להיות בטוח שזה מאותחל. אני רוצה לקבל מהמודול אובייקט שאוכל להשתמש בו בלי לדאוג שהוא לא מאותחל.
-
@dovid זה מה שרציתי לחסוך
ה-getDb הרי יחזיר פרומיס ולא DB ואז צריך לשרשר כל דבר עםthen
-ים...זה לא אמור להיות הבדל גדול כי כל הפעולות על ה-db הרי בין כך יהיו אסינכרנים אז מה איכפת לי שהמופע של ה-db גם אקבל בצורה אסינכרונית. אבל מה לעשות זה מעצבן אותי...
נראה לי שספריות אחרות לא עובדים כך (sequelize לדוגמה) אלא מחזירים את ה-db סינכרונית ורק את הפעולות עליו עושים אסינכרוני.toplevel await היה עוזר הרבה כאן.
-
@yossiz לא, אל תעשה פונקציה אסינכורנית, תעשה פונקציה שמחזירה משתנה.
אם אתה חושש שהקונקשיין עוד לא נטען (למרות שלא חששת לזה בפתרון הנאיבי האמור), תבטח את זה בלוגיקה של זרימת האפליקציה שיהיה שהות לפני הקריאה הראשונה, וגם אם לא, אז לא נורא, יהיה שגיאה בקריאה מוקדמת מידי.אכן נשגב מבינתי למה נוד לא עושים toplevel await (וגם למה הם לא הופכים הכל הכל במודולים שלהם מקאלבק לפרומייז).
-
-
@yossiz אמר בשימוש ב-MongoDB בנוד:
הפיתרון הוא לכאורה להחזיר אובייקט שיעטוף את ה-
db
. כל פונקציה שנקרא על העטיפה יעשה קודםawait
לאובייקט ה-db
האמיתי ואז יעביר את הפונקציה הלאה לאובייקט האמיתי.האם יש דרך לעשות עטיפה כזאת בלי יותר מדי boilerplate? פשוט להגיד ל-JS שכל פונקציה שאני יקרא על האובייקט לא משנה מה השם שלו יעבור דרך קוד העטיפה?
לא מבין את הבעיה
הקלאס מיד חוזר מכיל בתוכו את ה-DB
ופונקציתinsert({1:2})
יכיל בתוכו בדיקה אם ה-DB מחובר, ומחזיר תמיד פרומיז.כך תמיד עושים?!
-
@dovid אמר בשימוש ב-MongoDB בנוד:
נוד מאמצת ממש לאט את ההתקדמויות האלה
שמח שהם מאפשרים לדנו לעקוף אותם בקלות
-
@אהרן אמר בשימוש ב-MongoDB בנוד:
ופונקצית insert({1:2}) יכיל בתוכו בדיקה אם ה-DB מחובר, ומחזיר תמיד פרומיז.
הפונקציה
insert
מוגדר כבר על ה-db. לא רציתי לעבור על כל הפונקציות של ה-db ולהעתיק אותם לקלאס. בשביל זה ביקשתי משהו שחוסך boilerplate.
בשפות דינאמיות אחרות יש אפשרות להגדיר פונקציה שירוץ אם קוראים לפונקציה לא קיימת על אובייקט. אם זה היה קיים ב-JS הייתי יכול לעשות פרוקסי ל-DB בקלות עם מעט מאוד קוד. -
@yossiz אמר בשימוש ב-MongoDB בנוד:
בשפות דינאמיות אחרות יש אפשרות להגדיר פונקציה שירוץ אם קוראים לפונקציה לא קיימת על אובייקט. אם זה היה קיים ב-JS הייתי יכול לעשות פרוקסי ל-DB בקלות עם מעט מאוד קוד.
זה קיים!
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy