דילוג לתוכן

מדריכים - NodeJS

1 נושאים 5 פוסטים
  • מדריך | יצירת שרת אקספרס

    5
    11 הצבעות
    5 פוסטים
    736 צפיות
    אלישיא
    בניית מסד נתונים בפורמט json על-מנת להבין את רעיון העבודה בין צד לקוח לצד שרת, נתחיל לבנות מסד נתונים בפורמט json, כך שאם המשתמש יפנה דרך שורת הכתובת או דרך fetch לנתיב ספציפי שנגדיר, הוא יקבל את ה-json שלנו. ניצור בתיקיית src/routes קובץ בשם products.js ונדביק שם את תוכן הקובץ users.js. ניצור עוד קובץ בתיקייה src בשם products.json, ושם נכניס את json של האתר הזה. כעת נגדיר בקובץ products.js את השורה הבאה שבעצם קוראת ל-products.json: const productsjson = require("../products.json"); const myjson = productsjson['products']

    ולמטה נכתוב:

    router.get("/", (req, res) => { res.json(myjson); });

    בקובץ app.js נקרא לראוטר ככה:

    const products = require("./src/routes/products"); app.use("/products", products);

    מה שיקרה כרגע, שאם המשתמש פונה ל-url בנתיב products/ הוא יקבל קובץ json טהור.

    כרגע נגדיר שאם המשתמש יכניס ב-url מספר ID יוצג לו רק המוצר עם ה-id הייעודי. נוסיף בקובץ products.js את השורה הבאה: router.get("/:id", (req, res) => { res.json(myjson.products[req.params.id-1]); }); יצירת דף HTML להצגת המוצרים בצורה טבלאית וידידותית

    כדי שנוכל לצפות בתוצאות המתקבלות בצורה נוחה ולא רק כ-json טהור, ננווט לתיקייה הסטטית שעשינו בסעיף 11, וניצור שם קובץ HTML בשם index.html שם תכניסו את הקוד הבא:

    <!DOCTYPE html> <html lang="he" dir="rtl"> <head> <title>Products List</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous"> </head> <body> <div class="container mt-3"> <h2>רשימת מוצרים</h2> <p>להלן רשימת המוצרים שהתקבלו על פי החיפוש שלך:</p> <table class="table table-hover table-bordered"> <thead> <tr id="itemHead"> <!-- כאן מיובא הכותרת ע"י הקוד למטה --> </tr> </thead> <tbody id="itemRow"> <tr> <!-- כאן מיובא תוכן ה-json ע"י הקוד למטה --> </tr> </tbody> </table> </div> <script src="./index copy.js"></script> </body> </html>

    ניצור עוד קובץ בשם index.js שם נכניס את הקוד הבא (קוד נחמד כשלעצמו, מבוסס על תכנות מונחה עצמים):

    class Product { constructor(json, header, row) { this.rows = document.getElementById(row); this.head = document.getElementById(header); this.json = json; } //יוצר אלמנט ומכניס קלאס וטקסט createElement(name, text, src, className) { const el = document.createElement(name); el.innerText = text ? text : ""; el.src = src ? src : ""; el.classList = className ? className : ""; return el; } // יוצר כותרת לטבלה ע"י הנתונים מה-json createHeader() { let getKeys = this.json[0]; for (let key in getKeys) { if (key !== "images") { // console.log(`key: ${key}, value: ${getKeys[key]}`); let tableHead = this.createElement("th", key); // console.log(tableHead); this.head.append(tableHead); } } } //יוצר שורה לכל אובייקט נפרד createRow() { this.json.forEach((product) => { let row = this.createElement("tr"); //יוצר עמודה לכל איבר באובייקט for (let key in product) { //החרגת עמודת IMAGES if (key !== "images" && key !== "thumbnail") { // קבלת שמות של מפתחות של האובייקט הראשון for (let nameOfKey in this.json[0]) { console.log(nameOfKey); // השארת תא עמודה ריקה במידה ולא מופיע שם ערך if (key === nameOfKey) { // console.log(`key: ${key}, value: ${product[key]}`); let element = this.createElement("td", product[key]); row.append(element); //יוצר ID לכל שורה }} } else if (key === "thumbnail") { let element = this.createElement("img", null, product[key]); element.style.height = "75px"; row.append(element); // console.log(element); } row.id = product.id; //מחבר האלמנטים יחדיו //מכניס העמודות לשורה this.rows.appendChild(row); } // console.log(row); }); } } //יוצר קשר עם השרת וטוען קובץ JSON async function getProductsJson() { const getList = await fetch("http://localhost:3000/products"); return await getList.json(); } //פונה לקבלת JSON ושולח אותו לקלאס async function listOfProducts() { const list = await getProductsJson(); const item = new Product(list, "itemHead", "itemRow"); item.createHeader(); item.createRow(); } listOfProducts(); כעת, אם תריצו את השרת, תגיעו לקובץ index.html ותוכלו לצפות במסד הנתונים שלכם בצורה נחמדה. cors אם תריצו את הקובץ index.html לא דרך השרת, אלא דרך התוסף live server או פתיחת הקובץ דרך סייר הקבצים במחשב שלכם (כמובן כשהשרת מופעל, כדי לקבל את נתוני מסד הנתונים), תוכלו לראות בקונסול שגיאת אבטחה בשם CORS policy כזאת: Access to fetch at 'http://localhost:3000/products' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

    זוהי בעצם אבטחה לשרת שקוד זנודי של הלקוח לא יוכל לדלות מידע חסוי מהשרת, אבל אנחנו כן רוצים שהלקוח יוכל לצפות בתוכן ה-json שלנו ולכן נתקין מודול בשם cors, ונוסיף ב-app.js שלנו את השורות הבאות:

    const cors = require("cors");

    ובשורות של ה-app.use נוסיף:

    app.use( cors({ origin: "*", }) );

    הגדרה זו תתן ללקוח אפשרות לצפות בתכני השרת שנרצה לחשוף, כמובן שבמידה ונרצה שרק מהשרת יוכלו לפנות למסד הנתונים (כמו בהרצה רגילה של השרת ולא דרך live server שמדמה שרת חיצוני), נסיר הגדרה זו, אם תעשקו באבטחת מידע תוכלו ללמוד יותר על ההרשאות של תוסף זה, ולהגביל נתונים אותם לא תרצו בשום אופן לחשוף).

    שימוש במתודת post להוספת מידע

    מה נעשה במקרה והמשתמש ירצה להוסיף מידע למוצרים שלנו?
    נוסיף את השורות הבאות ל-product.js שלנו (שימו לב שלא הדגשתי כאן את השימוש בתיקייה controllers כדי לחסוך בכתיבה כאן, אבל רצוי ומומלץ להכניס את הקטעים הנוגעים לפעולת השרת לאחר קבלת הראוטר, ל-controllers כמו שהוסבר בסעיף 10).

    router.post("/add", (req, res) => { const newProduct = req.body; newProduct.id = myjson.length + 1; myjson.push(newProduct); fs.writeFile( path.join(__dirname, "../products.json"), JSON.stringify(productsjson), (err, result) => { if (err) console.log("error", err); } ); res.json(myjson[newProduct.id - 1]); });

    כרגע אם ניכנס לנתיב הזה products/add/
    ונדביק בקונסול את זה:

    var raw = JSON.stringify({ "description": "An apple mobile", "title": "apple " }); var requestOptions = { method: 'POST', body: raw, }; fetch("/products/add", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error));

    נקבל פלט של האובייקט החדש עם הערך החדש שנוסף.
    תוכן ההוספה לא תתעדכן בפועל בקובץ ה-json שלנו, לולי מה שכתבנו בשורה 5 עד 11, מה שעשינו שם זה המרת המערך בחזרה ל-json ואז דריסת הקובץ products.json עם הנתונים החדשים, (מומלץ לבצע בדוק גם גיבוי של הקובץ הישן, במקרה והשרת נופל תוך כדי הדריסה).

    כמובן שלצורך כך, נצטרך לקרוא למודולים המובנים fs ו-path כדי לעבוד עם הקוד הזה כך:

    const fs = require("fs"); const path = require("path");