זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/25/lessons/06-hello-node-lab
ינון שלום
קצת הסתבכתי עם תרגיל 2-1
קראתי לדמות Luke Skywalker יצרתי מערך של הפניות לכל הסרטים שהיא הופיעה בהם.
לפי הבנתי עכשיו אני צריך קריאות חדשות עבור כל סרט כדי להחזיר את שמו וכאן לא הצלחתי.
רצ"ב הקוד
כן אני רואה
בוא נניח שהייתי מבקש ממך לכתוב מאפס תוכנית שלוקחת URL של סרט ומדפיסה את השם שלו. זה קל לעשות כי זה כמעט זהה למה שכתבת.
אז עכשיו נדמיין שכתבת את התוכנית הזאת תוכל לעטוף את כל הקוד שלה בפונקציה גדולה בשם לדוגמה printFilmName, שתקבל URL ותדפיס שם של סרט, נגיד משהו בסגנון הזה (רק כמובן צריך לתקן את המימוש):
function printFilmName(url) {
const myUrl = new url.URL("https://swapi.dev/api/people/1");
const req = https.request(myUrl);
const filmArr = [];
//let reqFilm = https.request(null);
req.on("response", function (res) {
console.log(res.statusCode);
res.on("data", function (chunk) {
console.log(String(chunk));
const data = JSON.parse(chunk);
console.log(data);
for (film of data.films) {
filmArr.push(film);
//getFilmName(film);
}
});
});
req.on("error", function (err) {
console.log("error:", err);
});
req.on("close", function () {
for (i = 0; i < filmArr.length; i++) {
console.log(filmArr[i]);
getFilmName(filmArr[i]);
}
});
req.end();
}
ואז אחרי שיש לך פונקציה כזאת, שעושה את כל השטיקים עם אירועים וכל הדברים, אתה יכול להפעיל אותה מתוך הקוד הקיים שלך איפה שרצית לכתוב getFilmName שנמצא כרגע בהערה.
ובאמת התוצאה היא Flow שונה ממה שהיינו רגילים כי אנחנו קוראים לפונקציה, והיא יוצרת Event Handlers וחוזרת מיד אבל העבודה האמיתית שלה תבוצע רק אחרי שסיימנו לקרוא לה ואחרי שהקוד שלנו בכלל הסתיים. זה בדיוק המצב ב Node.JS וזה בדיוק המודל שצריך להתרגל אליו
ינון תודה על תשובתך
תיקנתי את הקוד כך
const https = require('https');
const url = require('url');
//printFilmName('https://swapi.dev/api/films/1/');
//printFilmName('https://swapi.dev/api/films/6/');
//https://swapi.dev/api/films/1/
getLukeSkywalkerFilms();
function getLukeSkywalkerFilms() {
const myUrl = new url.URL('https://swapi.dev/api/people/1');
const req = https.request(myUrl);
req.on('response', function (res) {
console.log(`getLukeSkywalkerFilms statusCode ${res.statusCode}`);
res.on('data', function (chunk) {
const data = JSON.parse(chunk);
for (film of data.films) {
printFilmName(film);
}
});
});
req.on('error', function (err) {
console.log('error:', err);
});
req.end();
}
function printFilmName(urlFilm) {
const myUrl = new url.URL(urlFilm);
const req = https.request(myUrl);
req.on("response", function (res) {
console.log(`printFilmName statusCode ${res.statusCode}`);
res.on("data", function (chunk) {
try{
const data = JSON.parse(chunk);
console.log(data.title);
} catch(e){
console.log('json information Corrupt');
}
});
});
req.on("error", function (err) {
console.log("error:", err);
});
req.end();
}
באופן מוזר אני מקבל את שמות 3 הסרטים הראשונים באופן תקין אבל לאחר מכן אני לא מצליח לקבל את שמות הסרטים הנוספים
מקבל את התשובה הזו
F:\ToCode\nodejs\05\ex3>node ex11.js
getLukeSkywalkerFilms statusCode 200
printFilmName statusCode 200
A New Hope
printFilmName statusCode 200
Return of the Jedi
printFilmName statusCode 200
The Empire Strikes Back
printFilmName statusCode 200
json information Corrupt
json information Corrupt
נראה שהקריאה לא תקינה
בתוך הקוד שלך שתופס Exception בבקשה תוסיף הדפסה מה התוכן שהגיע מהשרת - כלומר את השורה:
console.log(chunk.toString());
אתה תגלה שבפעמים שה JSON.parse שלך נכשל זה בגלל שה JSON מגיע מפוצל למספר chunk-ים. בשביל להתמודד עם מצבים כאלה כדאי ב data להוסיף את ה chunk לאיזשהו Buffer ולטפל גם באירוע end ובו לעשות את ה JSON.parse. אתה יכול לראות דוגמה למנגנון הזה בתיעוד שלהם כאן:
https://nodejs.org/api/http.html#httpgeturl-options-callback
תודה עובד
function printFilmName(urlFilm) {
const myUrl = new url.URL(urlFilm);
const req = https.request(myUrl);
req.on("response", function (res) {
//console.log(`printFilmName statusCode ${res.statusCode}`);
let data = '';
res.on("data", function (chunk) {
try{
data = data + chunk;
//console.log(data.title);
} catch(e){
console.log('json information Corrupt');
// console.log(chunk.toString());
}
});
res.on('end', function () {
// console.log('BODY: ' + data);
console.log(JSON.parse(data).title);
});
});
req.on("error", function (err) {
console.log("error:", err);
});
req.end();
}