fetch()
يتيح لك تقديم طلبات إلى الشبكة مشابهة لطلبات XMLHttpRequest (XHR). ويتمثل الاختلاف
الرئيسي في أنّ واجهة برمجة التطبيقات Fetch API تستخدم وعدًا، والذي يحتوي على واجهة برمجة تطبيقات
أبسط لمساعدتك في تجنُّب عمليات الاستدعاء المعقّدة في واجهة برمجة التطبيقات
XMLHttpRequest API.
إذا لم يسبق لك استخدام الوعد من قبل، اطّلِع على مقدّمة عن وعد 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()
إلى سوى طلب واحد لتنفيذ العمل نفسه الذي يؤديه مثال fetch()
. لمعالجة الاستجابة، نتحقّق أولاً من أنّ حالة الاستجابة هي
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
مع قيود على ما يمكنك الاطّلاع عليه من الاستجابة.
إذا تم تقديم طلب لمورد على مصدر آخر، وأعاد هذا المصدر
عناوين 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()
، يتيح لك ذلك مشاركة المنطق على مستوى طلبات الجلب.
إذا كنت تستخدم واجهة برمجة تطبيقات JSON، عليك التحقّق من الحالة وتحليل ملف ملف JSON لكل استجابة. يمكنك تبسيط الرمز البرمجي من خلال تحديد الحالة وتحليل ملف JSON في دوال منفصلة تعرض الوعود، واستخدام طلب fetch للتعامل مع البيانات النهائية وحالة الخطأ فقط.
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'
})