مقدمة إلىFetch()

fetch() يتيح لك تقديم طلبات إلى الشبكة مشابهة لطلبات XMLHttpRequest (XHR). يتمثل الاختلاف الرئيسي في أن واجهة برمجة تطبيقات الجلب تستخدم Promises، والتي تحتوي على واجهة برمجة تطبيقات أبسط لمساعدتك في تجنب عمليات الاستدعاء المعقدة في واجهة برمجة تطبيقات XMLHttpRequest.

توافق المتصفّح

  • Chrome: 42.
  • الحافة: 14.
  • Firefox: 39
  • ‫Safari: 10.1

المصدر

إذا لم يسبق لك استخدام الوعد من قبل، اطّلِع على مقدّمة عن وعد 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);
  });

يحتاج طلب fetch() إلى استدعاء واحد فقط لأداء العمل نفسه كمثال XHR. لمعالجة الاستجابة، نتحقّق أولاً من أنّ حالة الاستجابة هي 200، ثمّ نفكّك الاستجابة بتنسيق JSON. الاستجابة لطلب fetch() هي كائن Stream، ما يعني أنّه بعد استدعاء الطريقة json()، يتم عرض وعد. يحدث البث بشكل غير متزامن.

البيانات الوصفية للردّ

أظهر المثال السابق حالة الكائن 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 يسمح بطلبات مواد العرض من المصدر نفسه والمصادر الأخرى التي تُعيد عناوين 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()، يتيح لك هذا الإجراء مشاركة المنطق في جميع طلبات الجلب.

إذا كنت تستخدم واجهة برمجة تطبيقات 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.resolve() أو وعد مرفوض على النحو التالي: Promise.reject(). هذه هي الطريقة الأولى التي يتم استدعاءها في سلسلة fetch().

إذا تم حلّ الوعد، يستدعي النص البرمجي الطريقة json() التي تُعيد وعدًا ثانيًا من طلب response.json() وتُنشئ عنصرًا يحتوي على ملف JSON الذي تم تحليله. إذا تعذّر التحليل، يتم رفض الوعد ويُنفَّذ بيان المعالجة.

تتيح لك هذه البنية مشاركة المنطق في جميع طلبات الجلب، ما يسهّل صيانة الرمز البرمجي وقراءته واختباره.

طلب POST

في بعض الأحيان، يحتاج تطبيق الويب إلى استدعاء واجهة برمجة تطبيقات باستخدام طريقة 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);
  });

إرسال بيانات الاعتماد من خلال طلب استرجاع

لتقديم طلب جلب باستخدام بيانات اعتماد مثل ملفات تعريف الارتباط، اضبط قيمة credentials للطلب على "include":

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