בשנים האחרונות, ככל שהשימוש בפריימוורקים גדולים כמו Angular, react, vue ודומיהן הולך ומתרחב, כך יורד הצורך שלי לממש AJAX באופן טבעי (מה שנקרא נייטיב או ג'אווהסקריפט ונילה – כלומחר ג'אווהסקריפט שעובד ישר בשרת בלי ספריות/עזרים כמו jQuery וחבריו). לכל הפריימוורקים האלו יש את הדרכים שלהם ליצור תקשורת עם השרת המרוחק שמפשטות מאוד את התהליך המאוד מסורבל של ליצור תקשורת אסינכרונית עם השרת. במקום ליצור אובייקט XMLHttpRequest ולהתחיל להתעסק עם קודי תגובה מסוג 4 או 3 אני יכול פשוט להשתמש ב-http$ ולקרוא ל-get אם אני באנגולר (למשל).
למרות זאת, לעתים יש צורך עז כן לעשות AJAX. אם אתם כותבים קומפוננטות עצמאיות או משתמשים בפריימוורק שאין בו אבסטרקציה ל-AJAX איך עושים את זה? עם fetch. זו דרך טבעית, קלה ופשוטה לממש AJAX שנתמכת בכל דפדפן (נכון לתאריך כתיבת שורות אלו כולם חוץ מאקספלורר 11 וגם לו יש פוליפיל שעובד יפה עם babel, אז אין תירוצים).
אז איך זה עובד? ראשית אני מניח שאתם מכירים את promise, זה פיצ'ר של ECMAScript 6 שמהווה נדבך חשוב בכל פיתוח הווב המודרני. אם אתם לא מכירים, לא צריך לדאוג, כל מה שצריך זה לקרוא את המאמר הזה שמסביר על הפיצ'ר הזה.
בגדול, fetch הוא אובייקט גלובלי שזמין בכל מקום בקוד שלנו ומקבל שני ארגומנטים – לאן אנחנו רוצים ליצור תקשורת וארגומנט נוסף של אפשרויות. נדגים עם האפשרות הפשוטה ביותר. בואו למשל נניח שאני רוצה ליצור קשר עם ה-API הנוח להפליא של בדיחות צ'אק נוריס: https://api.chucknorris.io/jokes/random ה-API הזה, למי שלא מכיר, מחזיר בדיחה אקראית על צ'אק נוריס בכל פעם. אם אני רוצה לממש את זה, אני אצטרך לעשות משהו כזה:
fetch('https://api.icndb.com/jokes/random1http://api.icndb.com/jokes/random', {})
.then((response) => {
return response.json();
})
.then((jsonObject) => {
document.write(jsonObject.value.joke);
});
בואו ונסביר לפני שמישהו יתעלף. קודם כל אנחנו מתחילים ב-fetch. פונקציה גלובלית שלא צריך לעשות כלום בשבילה. היא נמצאת שם. היא מקבל שני ארגומנטים. הראשון הוא האתר שאליו אנחנו מתחברים. אם ניכנס עם הדפדפן נגלה שאנחנו מקבלים אובייקט JSON. השני הוא אובייקט ריק. במידה ויש לנו הצלחה, fetch מחזיר promise שמעבירה אובייקט שנקרא response, על מנת לראות מה קורה אם היא מתממשת אני צריך להשתמש ב-then. מה שבא אחר כך זו פונקצית חץ של ECMAScript 6. אם אתם לא יודעים מה זה, הגיע הזמן ללמוד. כולם משתמשים בזה. בגדול זה כמו לכתוב:
.then(funtion(response) {
return response.json();
})
מה זה ה-response הזה? זה אובייקט של התגובה מהשרת. יש לנו מספר תכונות ומספר מתודות. כל מתודה שלו גם מחזירה promise. במקרה הזה השתמשתי במתודת json שמחזירה promise שהיא אובייקט ה-JSON המתקבל. כיוון שקל לשרשר promise הקוד נראה אלגנטי. בשרשור האחרון, של ה-promise שמתקבל מה-response.json, יש לי את אובייקט ה-JSON שמתקבל מהשרת ואני יכול לעשות איתו מה שאני רוצה.
לא מבינים עדיין? הנה התרשים שמסביר:
ואם מישהו רוצה לשחק עם זה, הנה דוגמה חיה מ-codepen:
See the Pen FETCH example by Ran Bar-Zik (@barzik) on CodePen.
טיפול בשגיאות
על מנת לתפוס את השגיאות, במידה והשרת המרוחק נפל, אני צריך להשתמש ב-catch. במקרה הזה אני פונה ל-API שלא קיים כדי לדמות שגיאות 404 פשוטה שעלולה להתרחש כאשר השרת המרוחק לא זמין. כל מה שאני עושה זה להשתמש ב-catch. זה נראה כך:
fetch('https://fail-api.lo-po.com/it-is-not-there', {})
.then((response) => {
return response.json();
})
.then((jsonObject) => {
document.write(jsonObject.value.joke);
})
.catch((error) => {
document.write(error);
});
הנה הדוגמה החיה שבה גם אפשר לשחק. ניתן להעביר את ה-catch במעלה שרשרת ה-promises אבל אם נמקם אותו בתחתית הוא יתפוס את כל השגיאות.
See the Pen FETCH error example by Ran Bar-Zik (@barzik) on CodePen.
אפשרויות
בכל הדוגמאות עד כה הראיתי אובייקט אפשרויות ריק, אבל אפשר לשנות אותו. הנה למשל בקשת POST שאני מעביר ל-mock API שבעזרתו אני יכול לדמות בקשות POST:
const options = {
method: 'POST',
data: {
title: 'foo',
body: 'bar',
userId: 1
},
credentials: 'include',
headers: {}
};
fetch('http://jsonplaceholder.typicode.com/posts', options)
.then((response) => {
return response.json();
})
.then((jsonObject) => {
console.log(jsonObject)
document.write(`ID ${jsonObject.id} was created!`);
})
.catch((error) => {
document.write(error);
});
בעוד שהקריאה זהה למדי לקריאה ל-API של צ'אק נוריס, הדבר היחידי ששונה הוא היעד (כי אני שולח קריאה ל-API אחר) ואובייקט האפשרויות. שם פירטתי את ה-method שלי, במקרה הזה POST ואת המידע שאני שולח. יש שם גם אפשרות לשנות את ה-headers וגם את מדיניות משלוח העוגיות (ה-credentials למי שמכיר). לא חייבים לפרט את כל האפשרויות שיש לנו אלא לשנות רק את אלו שאנחנו רוצים לשנות. אם נשים למשל רק method באפשרויות זה יהיה גם מעולה. הנה הדוגמה החיה למי שרוצה לשחק.
See the Pen FETCH POST example by Ran Bar-Zik (@barzik) on CodePen.
בגדול, זהו. השימוש ב-fetch בהחלט אפשרי ואף יעיל ואין שום סיבה שלא להשתמש בו כבר עכשיו במיוחד אם אתם לא נעזרים בפריימוורק זה או אחר.
4 תגובות
אני חושב שאקנה את הדומיין https://fail-api.lo-po.com רק כדי להחזיר Response code 200 ולשבור לך את הדוגמה 😛
lol 😀
תקשיב…. אתה תותח!!!
מסביר ברור חלק, נקי ויפה!
שלום,
שאלה דחופה:
יש לי controller get מסויים,
כשאני שמה את הURL בכרום או פונה דרך post man מחזיר לי תוצאה כמו שאני רוצה.
אבל שאני פונה עם fetch כמו בדוגמא פה, התוצאה ב network היא ריק, כאילו אין תוצאה (סטטוס 200) :
export const getUserById = () => {
const request = new Request('http://localhost:53824/api/esr_Users/1');
fetch(request, {method: 'GET',mode: 'no-cors'})
.then((response) => console.log("response", response));
}
1593113195092.png 1593113195092.png 1593113195092.png
מדפיס לי ללוג:
response
Response {type: "opaque", url: "", redirected: false, status: 0, ok: false, …}
body: null
bodyUsed: false
headers: Headers {}
ok: false
redirected: false
status: 0
statusText: ""
type: "opaque"
url: ""
__proto__: Response
איך אני יכולה לראות את התשובה?
יש למישו מידע?
זה דחוף לי מאוד!!!
אשמח לעזרה.
תודה!