fetch()
מאפשר לשלוח בקשות רשת שדומות ל-XMLHttpRequest (XHR). ההבדל העיקרי הוא שב-Fetch API נעשה שימוש ב-Promises, שיש לו ממשק API פשוט יותר שעוזר להימנע מהקריאות החוזרות המורכבות ב-XMLHttpRequest API.
אם זו הפעם הראשונה שאתם משתמשים ב-Promises, כדאי לעיין במאמר מבוא ל-Promises ב-JavaScript.
בקשת אחזור בסיסית
דוגמה להטמעה באמצעות XMLHttpRequest
ואז באמצעות fetch
. אנחנו רוצים לבקש כתובת URL, לקבל תשובה ולנתח אותה כ-JSON.
XMLHttpRequest
ל-XMLHttpRequest
נדרשים שני מאזינים כדי לטפל במקרים של הצלחה ושגיאה, וקריאה ל-open()
ול-send()
.
דוגמה ממסמכי MDN.
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
הבא
בקשת האחזור שלנו נראית כך:
fetch('./api/some.json')
.then(response => {
if (response.status !== 200) {
console.log(`Looks like there was a problem. Status Code: ${response.status}`);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
כדי לבצע את אותה עבודה כמו בדוגמה של ה-XHR, צריך רק קריאה אחת לבקשת fetch()
. כדי לעבד את התגובה, קודם כול בודקים שסטטוס התגובה הוא 200, ואז מנתחים את התגובה כ-JSON. התגובה לבקשה fetch()
היא אובייקט Stream, כלומר אחרי שאנחנו קוראים ל-method json()
, מוחזר Promise.
השידור מתבצע באופן אסינכרוני.
מטא-נתונים של תגובה
בדוגמה הקודמת הוצג הסטטוס של האובייקט Response, והוסבר איך לנתח את התגובה כ-JSON. כך מטפלים במטא-נתונים אחרים שרוצים לגשת אליהם, כמו כותרות:
fetch('users.json').then(response => {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
סוגי תגובות
כששולחים בקשת אחזור, הערך של response.type
בתגובה הוא basic
, cors
או opaque
. הערכים האלה של types
מצביעים על המקור של המשאב, וניתן להשתמש בהם כדי לקבוע איך לטפל באובייקט התגובה.
כשהדפדפן מבקש משאב מאותו מקור, התגובה היא מסוג basic
עם הגבלות על מה שאפשר לראות בתגובה.
אם נשלחת בקשה למשאב ממקור אחר, והמקור הזה מחזיר כותרות CORS, הסוג הוא cors
. התשובות של cors
דומות לתשובות של basic
, אבל הן מגבילות את הכותרות שאפשר להציג ל-Cache-Control
, Content-Language
, Content-Type
, Expires
, Last-Modified
ו-Pragma
.
תגובות opaque
מגיעות ממקור אחר שלא מחזיר כותרות CORS. אם התשובה תהיה לא שקופה, לא נוכל לקרוא את הנתונים שהוחזרו או לראות את סטטוס הבקשה, כלומר לא תוכלו לבדוק אם הבקשה בוצעה.
אפשר להגדיר מצב לבקשת אחזור כך שרק סוגים מסוימים של בקשות יתקבלו. אלה המצבים שאפשר להגדיר:
same-origin
מצליח רק לבקשות לנכסים באותו מקור, ודחה את כל הבקשות האחרות.cors
מאפשר בקשות לנכסים באותו מקור ובמקורות אחרים שמחזירים את כותרות ה-CORS המתאימות.cors-with-forced-preflight
מבצע בדיקה לפני ההפעלה לפני שליחת בקשה.no-cors
מיועד לשלוח בקשות למקורות אחרים שאין להם כותרות CORS, וכתוצאה מכך לקבל תגובה מסוגopaque
. עם זאת, כפי שצוין, אי אפשר לעשות זאת כרגע ברמת החלון הגלובלי.
כדי להגדיר את המצב, מוסיפים אובייקט אפשרויות כפרמטר השני בבקשה fetch
ומגדירים את המצב באובייקט הזה:
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
שרשרת הבטחות
אחת מהתכונות הגדולות של הבטחות היא היכולת לשרשר אותן זו לזו. ב-fetch()
, כך אפשר לשתף לוגיקה בין בקשות אחזור.
אם אתם עובדים עם API בפורמט JSON, עליכם לבדוק את הסטטוס ולנתח את ה-JSON של כל תשובה. כדי לפשט את הקוד, אפשר להגדיר את הסטטוס ופירוק ה-JSON בפונקציות נפרדות שמחזירות הבטחות (promises), ולהשתמש בבקשת האחזור כדי לטפל רק בנתונים הסופיים ובמקרה השגיאה.
function status (response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json (response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
בדוגמה הזו מוגדרת פונקציית status
שבודקת את response.status
ומחזירה Promise שהתקבל כ-Promise.resolve()
או Promise שנדחה כ-Promise.reject()
.
זו השיטה הראשונה שנקראת בשרשרת fetch()
.
אם ה-Promise מתקבל, הסקריפט קורא ל-method json()
, שמחזיר Promise שני מהקריאה ל-response.json()
ויוצר אובייקט שמכיל את ה-JSON שעבר ניתוח. אם הניתוח נכשל, ה-Promise נדחה והצהרת ה-catch מתבצעת.
המבנה הזה מאפשר לשתף את הלוגיקה בין כל בקשות האחזור, וכך קל יותר לתחזק, לקרוא ולבדוק את הקוד.
בקשת POST
לפעמים אפליקציית אינטרנט צריכה לקרוא ל-API באמצעות שיטת POST ולכלול כמה פרמטרים בגוף הבקשה. כדי לעשות זאת, מגדירים את הפרמטרים method
ו-body
באפשרויות fetch()
:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
שליחת פרטי הכניסה עם בקשת אחזור
כדי לשלוח בקשת אחזור עם פרטי כניסה כמו קובצי cookie, מגדירים את הערך של credentials
בבקשה כ-"include"
:
fetch(url, {
credentials: 'include'
})