באמצעות fetch()
אפשר ליצור בקשות רשת הדומות ל-XMLHttpRequest (XHR). ההבדל העיקרי הוא שב-Fetch API נעשה שימוש ב-Promises, שיש לו ממשק API פשוט יותר שעוזר להימנע מהקריאות החוזרות המורכבות ב-XMLHttpRequest API.
אם זו הפעם הראשונה שאתם משתמשים ב-Promises, כדאי לקרוא את המאמר Introduction to JavaScript Promises.
בקשת אחזור בסיסית
דוגמה להטמעה באמצעות 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
עם הגבלות על המידע שתוכלו לראות מהתשובה.
אם נשלחה בקשה למשאב ממקור אחר, והמקור הזה מחזיר כותרות COR, הסוג הוא cors
. התשובות של cors
דומות לתשובות של basic
, אבל הן מגבילות את הכותרות שאפשר להציג ל-Cache-Control
, Content-Language
, Content-Type
, Expires
, Last-Modified
ו-Pragma
.
תגובות opaque
מגיעות ממקור אחר שלא מחזיר כותרות CORS. בתגובה אטומה, לא נוכל לקרוא את הנתונים שהוחזרו או להציג את סטטוס הבקשה, כלומר לא תוכלו לבדוק אם הבקשה הצליחה.
אפשר להגדיר מצב לבקשת אחזור, כך שרק סוגי בקשות מסוימים יטופלו. אלה המצבים שאפשר להגדיר:
same-origin
מצליח רק בבקשות לנכסים מאותו המקור ודוחה את כל הבקשות האחרות.- הפקודה
cors
מאפשרת בקשות לנכסים מאותו המקור ובמקורות אחרים שמחזירים את כותרות ה-COR המתאימות. 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 בפונקציות נפרדות שמחזירות הבטחות, ולהשתמש בבקשת האחזור כדי לטפל רק בנתונים הסופיים ובתרחיש השגיאה.
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 שעבר ניתוח. אם הניתוח נכשל, ההבטחה נדחית והצהרת השליפה תפעל.
המבנה הזה מאפשר לשתף את הלוגיקה בכל בקשות האחזור, וכך קל יותר לתחזק, לקרוא ולבדוק את הקוד.
בקשת 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'
})