שאלות של מתחיל - מקצועי ב nodejs
-
התחלתי ללמוד nodejs, או יותר נכון התחלתי לפתח.. (אם אתיישב ללמוד ואח"כ אתחיל לפתח, אוי ואבוי, כל השיטה היא שמתחילים מיד עם תוכנית עבודה..)
כמה שאלות:
א. להבין את המבנה איך מפתחים ומעדכנים קבצי קוד.
לפי מה שהבנתי לאחר כתיבת הקוד הראשון בקובץ js עלי להפעיל אותו ע"י הפקודה
myapp.js nodejs
דבר ראשון אני רוצה להבין מה קורה כאן, אני רואה שהפקודה לא נעצרת, אני לא מקבל תשובה. ומצד שני לאחר שביצעתי שינויים בקובץ ואני רוצה לעדכן את השרת הרצתי שוב את הפקודה הנ"ל וזה נכשל כי הפורט כבר היה תפוס, מגלגול בגוגל הבנתי שעלי לחפש את התהליך ולהרוג אותו, וזה מה שעשיתי ואז ניתן היה לאחל מחדש.
היה נשמע לי מסורבל, גילגלתי עוד ומצאתי שיש משהו nodemon שעוקב אחרי הקובץ, וברגע שאני משנה אותו הוא מבצע את השינויים בשרת, בלי שאצטרך לבד לאתחל את התהליך.
אשמח להבין האם זו אכן הדרך?
ב. איך בעצם יוצרים כמה אפלקציות? בקוד זה למשל:var http = require('http'); var url = require('url'); var fs = require('fs'); http.createServer(function (req, res) { var q = url.parse(req.url, true); var filename = "." + q.pathname; fs.readFile(filename, function(err, data) { if (err) { res.writeHead(404, {'Content-Type': 'text/html'}); return res.end("404 Not Found"); } res.writeHead(200, {'Content-Type': 'text/html'}); res.write(data); return res.end(); }); }).listen(8080);
מקור https://www.w3schools.com/nodejs/nodejs_url.asp
ראיתי איך לנווט לקבצים לפי הנתיב שכתבתי. רק ששם זה רק הדפסה מתוך הקובץ, אני רוצה לדעת איך לנווט מראש לסקריפט/פונקציות באמצעות נתיב הקובץ
האם עלי לעשות קובץ ראשי שמאזין לפורט 80 וינתב את הסקריפט למודל לפי הנתיב? או משהו אחר? בקיצור איך זה למישהו שמגיע מPHP...
ג. איך אני יוצר תתי קבצים של פונקציות, שאוכל לגשת אליהם בלי להצטרך להכניס אותם למשתנה ולגשת מתוך המשתנה, יותר נכון אני רוצה אותם בצורה גלובאלית, דומה ל
include 'CreditCard.php';
בשפת PHP.
מצאתי את זה https://stackoverflow.com/questions/5797852/in-node-js-how-do-i-include-functions-from-my-other-files יש שם בתשובה הרביעית משהו שהיה נראה יחסית הכי קל, אבל עדיין זה לא גמיש.
ד. וכהמשך לג' אני רוצה לעשות קבועים בקובץ נפרד, איך עושים את זה?
ה. אני רוצה לגשת לפרמטרים של הURL מתוך פונקציה וכן להדפיס תשובה למסך מתוך אותה פונקציה, אני חייב להעביר את req, res לפונקציה? או שניתן לגשת אליהם כגלובאלי או משהו אחר?
ו. בסופו של דבר, כל השרת אמור להיות כתוב בסופו של דבר בקובץ אחד, (כמובן שניתן לייבא מודולים, אבל האם בתכלית זה הפליקציה אחת בלבד), או שכן ניתן לעשות משהו בדומה לPHP וHTML שהנתיב מפנה לקוד להרצה
חכו לשאלות בהמשך...
@dovid אתה אשם, אתה צריך לעזור לי...
תודה -
דבר ראשון תצא מהראש של התכנות (שעובד אצלך רק בPHP) ותעבור לראש של התוצאה (אני רוצה שurl פלוני יחזיר תוצאה X).
הניסיון לתרגם את איך שאתה עבדת עד עכשיו לנוד הוא בסדר, ולא נועד לכישלון אבל מ-י-ו-ת-ר.
תפסיק, אל תילך בגדול כמו שאתה רגיל. תעשה נטו קובץ בודד שמחזיר תוצאות רצויות לurl מתאים.
ואז, בלי לקחת בחשבון כל מה שעשית בהצלחה רבה בPHP, תחשוב מה חסר לי ומה יקל עלי כדי לגדול*, אל תינעל על מה שהכרת!טוב כעת אני יענה תשובה תשובה:
שאלה א.
כשמריצים סקריפט עם נוד, הוא רץ כל עוד לא מתבצע בו procces.exit או שגיאה. אחרת אתה אכן חייב להרוג את הראשון.
בשביל לא לעבוד קשה תעבוד עם IDE,
מה שאני ממליץ לא לפתח ישירות על השרת אלא במחשב שלך עם VSCODE. לגבי החיבור למסד תחזיק מקומי מדומה או שתפתח את המרוחק לגישה מרוחקת,
אבל תוכל גם לפתח בC9 (ישירות על השרת המרוחק), זה מאוד מקל את החיים אבל הIDE פחות מפותח. שמה ההרצה וההריגה זה כפתורים נוחים ופשוטים.שאלה ב.
ניתוב לפונקציה מתאימה לפי URL זה אכן מתבקש (ניתוב לקובץ/סקריפט לפי URL זה לא משהו טוב אלא משהו שהורגלת בו, שכח מזה, לא בגלל שזה בעיה אלא כי זה לא משהו שיש בו תועלת כל שהיא).
בנוד אתה צריך לעשות את זה בעצמך (לכתוב if else ארוכים וכיוצ"ב) או להשתמש בספריה. הספריה המפורסמת ביותר של נוד שכולם משתמשים בה נקראת express והיא מעניקה את האפשרות הזו. יש לה מנוע ניתוב משוכלל ומלא פיצ'רים.שאלה ג.
לא. אתה לא יכול ולא צריך.
בשביל ליצור פונקציות ולהשתמש בהם מרחבי ה"פרוייקט" אתה יוצר מודול, ומבצע export ומייבא אותו לתוך משתנה. אם אתה רוצה לוותר על השם, סימן שהפונקציה צריכה להיות באותו הקובץ. אם מפריע לך קבצים גדולים אתה צריך להתרגל כי זה אכן חיסרון של JS שא"א לפרוס קוד ארוך על פני כמה קבצים בלי שתהיה גם חלוקה סמנטית למודולים נפרדים.שאלה ד.
אפשר בדיוק כמו ג', אבל להגדיר פרמטרים בקובץ JSON ולטעון תכנותית את ההגדרות במודול או בסקריפט הראשי.שאלה ה.
מה הכונה "אני חייב"? זה עולה כסף? למה לא? בשום אופן לא גלובלי... כי הגלובלי משותף בין כל הבקשות! אתה עוד תחגוג עם ההבנה הזו - זו מעלה עצומה.שאלה ו.
כן, אבל בקובץ הזה יכול להיות הפעלה להמון קבצים אחרים.אשמח לשאלות נוספות!
אקוה שאנשים כמו @magicode יסתובבו פה כי הם מפתחים בנוד ואני לא...
אני (אם בכלל) מפתח בaps mvc core. -
הוספה קטנה לשאלה ג'
א. הדרך המקובלת היא כמו שאמר דוד, לכתוב את הפונקציה בקובץ כך://child-script.js function globalFunc(){ console.log("A") } module.exports = globalFunc;
ולייבא אותו כך
//main-script.js var globalFunc = require('./child-script.js') globalFunc()
אפשר גם ליצור משתנים גלובליים ממש, אם אתה מאתחל את המשתנה בלי להצהיר עליו עם var או let או function וכדומה, לדוגמא:
globalFunc = function(){ console.log("A") } globalVar = "globalVar"
ואז אתה עושה ממש כמו include בקובץ הראשי או בכל קובץ שהוא ממרחבי האפליקציה:
require('./child-script.js') globalFunc() console.log(globalVar )
והמשתנים האלה זמינים לך בכל האפליקציה.
אבל זכור לי שלא ממליצים לעבוד כך, כי זה יכול לגרום התנגשות בין משתנים בלי שימת לב, וגם אם אתה עובד עם IDE נורמלי כמו vscode הוא לא יודע לזהות את המשתנים ולא יתן לך הצעות להשלמה אוטומטית. -
@חוקר אמר בשאלות של מתחיל - מקצועי ב nodejs:
עוד משהו, בקשר לסביבת פיתוח, זה באמת חיסרון בשפות האלה יחסית ל PHP שצריך להשקיע יותר בסביבת פיתוח ואין את הפשטות של עריכת קובץ ושמירה, צריך קצת להתרגל לזה, אבל בשום אופן לא לפתח ישירות על השרת.
אני ממליץ על vscode, זה מגיע עם IDE אינטגרלי עבור נוד וזה מאד מקל על העבודה, אפשר לדבג לכבות ולרסט את השרת בקלות, יש הודעות שגיאה עם מצביע למיקום השגיאה, ההדפסה לקונסול בגירסאות האחרונות מאד משוכללת, זה מציין את השורה שמשם התבצעה הבקשה להדפסה (וזה מאד משמעותי כשאתה רוצה לדבג וללכוד שגיאות) זה מדפיס אובייקטים כמו שהדפדפן כרום מדפיס אותם עם אפשרות לפתוח לראות את כל השרשרת של האובייקט והמורישים שלו.
גם דבר חשוב , vscode מציע לך השלמה אוטומטית לפרמטרים ושאר ירקות, הוא תומך בטייפסקריפט וב jsdoc שמודיעות לך לאיזה סוגי משתנים הפונקציה מצפה, וזה משמעותי כשאתה משתמש בספריה חיצונית במקום לדפדף בין הקוד להדרכות של המפתח של הספריה.
ויש עוד מעלות שאיני זוכר כרגע, בכל אופן מאד מומלץ
בהצלחה -
עדיין לא התלהבתי מnodejs, אני צריך לעלות שלב למשהו יותר דינאמי, לחבר עליו מערכת אמיתית.
בינתיים בניתי מערכת אם התסריט הזה:
עדיין אינך רשום במערכת, הינך מועבר להרשמה חד פעמית
הקלט את שמך המלא, ולסיום הקש סולמית
הקש טלפון ליצירת קשר ולסיום הקש סולמית
לאחר הצליל הקלט את כתובתך המלאה, ולסיום הקש סולמית
השם שנקלט הוא
מספר הטלפון שהוקש הוא
הכתובת שהוקלטה היא
שלום ותודהנראה בהמשך מה הלאה
תודה בכל אופן על ההדרכות.
עדיין אני עובד משורת הפקודה, עדיין לא עם IDE.
מה שאני לא מבין שאחרי ביצוע שינויים בקובץ אני מקבל פלט:[nodemon] starting `node nodejs/test.js` events.js:183 throw er; // Unhandled 'error' event ^ Error: listen EADDRINUSE :::80 at Object._errnoException (util.js:1022:11) at _exceptionWithHostPort (util.js:1044:20) at Server.setupListenHandle [as _listen2] (net.js:1367:14) at listenInCluster (net.js:1408:12) at Server.listen (net.js:1492:7) at Object.<anonymous> (/home/ubuntu/nodejs/test.js:15:4) at Module._compile (module.js:652:30) at Object.Module._extensions..js (module.js:663:10) at Module.load (module.js:565:32) at tryModuleLoad (module.js:505:12) [nodemon] app crashed - waiting for file changes before starting...
אך בכל זאת השינויים מבוצעים ועובדים כפי השינויים, איך זה ייתכן? מה לא נכון בהבנה שלי?
-
@dovid @magicode
שאלה נוספת
לשם ההבנה, ברעיון זה אפשרי ותיקני לכתוב כמה קבצים נפרדים, וכל אחד יוגדר על פורט אחר, ולהפעיל אותם במקביל, ואז בעצם יש לנו כמה תהליכים של הנוד שהם פעילים בו זמנית כל אחד ליציאה אחרת?
כך היה נראה לי מהנסיונות שלי, כאשר הרצתי סקריפט חדש על פורט אחר, ושני הפורטים ממשיכים לעבוד.
האם זה בסדר? -
@WWW אמר בשאלות של מתחיל - מקצועי ב nodejs:
@clickone איך שהבנתי, במקרה שעובדים עם אסטריסק, יורדת הנחיצות לעובר ל node,
כי בין כך הקוד באמצע השיחה, לא כך?אדרבא זה אמור לעלות לדעתי.
כי אם זה תוך כדי קוד זה אומר שהבקשה תקועה כשהקוד ממתין למענה מאסטריסק.
ובקשה תקועה זה יקר, בPHP. -
@חוקר אני לא מכיר את החבילה הזו שאתה משתמש, לפי הפלט זה נראה שהוא מנסה להריץ פעמיים את האפליקציה ויש התנגשות בגלל ששתיהם מאזינות לאותו פורט, אולי אתה מעדכן בבת אחת שני קבצים אז הוא יורה פעמיים את העדכון?
בכל אופן לשאלתך איך השינויים מתבצעים, כנראה הפעם הראשונה נכשלת והפעם השניה עובדת -
@חוקר אמר בשאלות של מתחיל - מקצועי ב nodejs:
לשם ההבנה, ברעיון זה אפשרי ותיקני לכתוב כמה קבצים נפרדים, וכל אחד יוגדר על פורט אחר, ולהפעיל אותם במקביל, ואז בעצם יש לנו כמה תהליכים של הנוד שהם פעילים בו זמנית כל אחד ליציאה אחרת?
כך היה נראה לי מהנסיונות שלי, כאשר הרצתי סקריפט חדש על פורט אחר, ושני הפורטים ממשיכים לעבוד.
האם זה בסדר?
זה תקני כאשר אתה מריץ כמה אפליקציות נפרדות על אותו שרת, אז כל אפליקציה מאזינה לפורט אחר, אם מדובר באותה אפליקציה זה מיותר ומבזבז משאבים בלי צורך.
אם אני מבין נכון, מה שמניע אותך זה לקבל את נוד כמה שיותר דומה ל PHP, אז זה ניסיון סרק, אם אתה רוצה שרת פעיל במהירות, פשוט תתקין express. תכתוב את הפונקציות שאמורות לטפל בכל בקשה לפי ה URL, ותעשה ניתוב לפונקציה, יש מדריך טוב באתר של רן בר זיק על אקספרס וראוטינג. תתחיל ותדווח איפה נתקעת.
https://internet-israel.com/category/מדריכים/express/ -
@dovid @יוסף-בן-שמעון
איך אני יכול לשלוף נתונים נתונים מתוך אתר אחר ולהחזיר אותם לתוך משתנה?
משהו בצורתvar datafromurl = fetch('https://github.com/'); if (datafromurl = "ok"){ res.end(datafromurl); } else{ res.end("no"); }
לא הצלחתי להחזיר את הנתונים לתוך משתנה.
אשמח לעזרה בהקדם.
תודה -
@חוקר אמר בשאלות של מתחיל - מקצועי ב nodejs:
נוד היא סינכרונית, כלומר כשאתה שולח בקשה לשרת מרוחק המעבד ממתין לתשובה, בנתיים הקומפיילר לא מחכה אלא ממשיך לשורה הבאה, ועד שהתשובה מגיעה הוא כבר אוחז כמה שורות אח"כ ולכן הוא לא טוען את התשובה למשתנה.
הפתרון היא לעבוד עם callback או עם promise, לדוגמא במודול שאתה משתמש יש פרומיס מובנה, תראה כאן:
https://www.npmjs.com/package/node-fetch#plain-text-or-htmlfetch('https://github.com/') .then(res => res.text()) .then(body => console.log(body));
then הראשון ממיר את התשובה מאובייקט לטקסט, ומחזיר אותו ל then השני, ובשני אתה יכול לשלוח את התשובה לאיפה שאתה רוצה. משהו כזה:
app.get('/page', (req, res)=>{ fetch('https://github.com/') .then(response => response.text()) .then(body =>{ if (body = "ok"){ res.end(body); } else{ res.end("no"); } }); })```
-
@יוסף-בן-שמעון
תודה.
השאלה היא האם שייך כן לארוז את זה כפונקציה, כי אני רוצה לקבל json ולטפל אותו לנתח נתונים לתוך משתנים ועוד.
אני צריך אפשרות לקבל בסגנון שכתבתי בהתחלה.
יש מצב?
תודה -
@יוסף-בן-שמעון אמר בשאלות של מתחיל - מקצועי ב nodejs:
הפתרון היא לעבוד עם callback או עם promise, לדוגמא במודול שאתה משתמש יש פרומיס מובנה
מה זה פרומיס?
-
@חוקר אמר בשאלות של מתחיל - מקצועי ב nodejs:
@יוסף-בן-שמעון אמר בשאלות של מתחיל - מקצועי ב nodejs:
הפתרון היא לעבוד עם callback או עם promise, לדוגמא במודול שאתה משתמש יש פרומיס מובנה
מה זה פרומיס?
-
@חוקר אמר בשאלות של מתחיל - מקצועי ב nodejs:
@יוסף-בן-שמעון
תודה.
השאלה היא האם שייך כן לארוז את זה כפונקציה, כי אני רוצה לקבל json ולטפל אותו לנתח נתונים לתוך משתנים ועוד.
אני צריך אפשרות לקבל בסגנון שכתבתי בהתחלה.
יש מצב?
תודהאתה יכול במקום לכתוב
res.text()
להחליף ל
res.json()
ואז בפונקציה השניה אתה מקבל את הbody כ JSON
אגב יש מודול יותר פופולרי לבקשות משרתים מרוחקים, קוראים לו request, אתה יכול להתקין כךnpm i request
ולהשתמש כך:
var request = require('request'); app.get('/page', (req, res)=>{ request('https://github.com/', (err, response, body)=>{ body = JSON.parse(body); if(body.status == "ok") res.send("ok") else res.send("no") }) })
-
@יוסף-בן-שמעון
מצאתי את מה שרציתי..
https://www.npmjs.com/package/sync-request