מבוא ל-fetch()

באמצעות fetch() אפשר ליצור בקשות רשת הדומות ל-XMLHttpRequest (XHR). ההבדל העיקרי הוא ש-Fetch API משתמש ב-Promises, ממשק API פשוט יותר שיעזור לכם להימנע מהקריאות החוזרות המורכבות API ל-XMLHttpRequest.

תמיכה בדפדפן

  • Chrome: 42.
  • קצה: 14.
  • Firefox: 39.
  • Safari: 10.1.

מקור

אם לא השתמשתם בעבר הבטחות מומלץ לקרוא קודם את המאמר מבוא להבטחות של JavaScript.

בקשת אחזור בסיסית

הנה דוגמה שהוטמעה באמצעות XMLHttpRequest ולאחר מכן עם fetch. אנחנו רוצים לבקש כתובת אתר, לקבל תשובה ולנתח כקובץ JSON.

XMLHttpRequest

ל-XMLHttpRequest נדרשים שני מאזינים כדי להתמודד עם ההצלחה ומקרים של שגיאות, וקריאה ל-open() ול-send(). דוגמה ממסמכי MDN.

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}

function reqError(err) {
    console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

הבא

בקשת האחזור שלנו נראית כך:

fetch('./api/some.json')
  .then(
  function(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(function(err) {
    console.log('Fetch Error :-S', err);
  });

לבקשת fetch() נדרשת רק קריאה אחת כדי לבצע את אותן פעולות כמו ה-XHR לדוגמה. כדי לעבד את התשובה, קודם אנחנו בודקים שסטטוס התגובה 200, ואז מנתחים את התשובה בתור JSON. התגובה לבקשת fetch() היא אובייקט Stream שפירושו שאחרי שאנחנו קוראים לשיטה json(), מוחזרת הבטחה. השידור מתרחש באופן אסינכרוני.

מטא-נתונים של התשובה

בדוגמה הקודמת הוצג הסטטוס של אובייקט Response, ואיך לנתח את התשובה בפורמט JSON. כך תטפלו במטא-נתונים שאולי תרצו לגשת אליהם, כמו כותרות:

fetch('users.json').then(function(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(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(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(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

בדוגמה הזו מוגדרת פונקציית status שבודקת את response.status מחזירה 'Promise' שמפוענח כ- Promise.resolve(), או הבטחה שנדחתה, Promise.reject(). זו השיטה הראשונה שנקראת בשרשרת fetch().

אם ה-Promise פותר את הבעיה, הסקריפט קורא לשיטה json(), מחזירה הבטחה שנייה מהקריאה response.json() ויוצרת שמכיל את קובץ ה-JSON שנותח. אם הניתוח נכשל, ההבטחה נדחה והצהרת ה-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(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

שליחת פרטי כניסה באמצעות בקשת אחזור

כדי לשלוח בקשת אחזור עם פרטי כניסה כמו קובצי cookie, צריך להגדיר את פרטי הבקשה הערך של credentials ל-"include":

fetch(url, {
    credentials: 'include'
})