إحدى أسوأ الأسرار التي تمَّ الاحتفاظ بها حول AJAX على الويب هو أنّ الواجهة البرمجية (API) الأساسية لها، XMLHttpRequest، لم توجد للغرض الذي نستخدمه الآن. لقد قمنا بعمل جيد في إنشاء واجهة برمجية جيّدة باستخدام الكائن XHR ولكننا نعرف أنه يمكننا القيام بعمل أفضل. نحن نبذل الجهود لتحقيق الأفضل الذي هو الواجهة البرمجية fetch. لنأخذ فكرة عامة عن التابع window.fetch
الجديد، المتوفر الآن في Firefox و Chrome Canary.
الكائن XMLHttpRequest
إنَّ كائن XHR معقد قليلًا برأيي ولا أريد أن أبدأ بشرح لماذا "XML" تُكتب بأحرف كبيرة بينما "Http" تُكتب بأسلوب سنام الجمل. على أيّة حال، لنلاحظ كيف نستخدم XHR.
// فوضى XHR فقط الحصول على if (window.XMLHttpRequest) { // موزيلا، سفاري... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // إنترنت إكسبلورر try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } // فتح، إرسال request.open('GET', 'https://davidwalsh.name/ajax-endpoint', true); request.send(null);
بالطبع إنَّ أطر عمل جافاسكربت الخاصة بنا تجعل XHR أكثر متعة للعمل، ولكن ما نراه في الأعلى هو مثال بسيط على فوضى XHR.
استخدام fetch الأساسي
تم توفير دالة fetch
في نطاق window
العام، الوسيط الأول له هو الرابط URL:
// الرابط (إلزامي)، الخيارات (اختيارية) fetch('https://davidwalsh.name/some/url', { method: 'get' }).then(function(response) { }).catch(function(err) { // خطأ :( });
وهذا يشبه إلى حد بعيد الواجهة البرمجية Battery المحدّثة، إذ تستخدم الواجهة البرمجية fetch الوعود في جافاسكربت لمعالجة النتائج/ردود النداء:
// معالجة رد بسيط fetch('https://davidwalsh.name/some/url').then(function(response) { }).catch(function(err) { // خطأ :( }); // "تسلسل لمعالجة أكثر "تطورًا fetch('https://davidwalsh.name/some/url').then(function(response) { return //... }).then(function(returnedValue) { // ... }).catch(function(err) { // خطأ :( });
إذا لم تكن معتادًا على استخدام then
، يجب أن تعتاد عليه لأنها ستنتشر قريبًا في كلّ مكان.
ترويسات الطلب
القدرة على ضبط ترويسات الطلب هي أمر مهم في مرونة الطلب. يمكنك العمل مع ترويسات الطلب بتنفيذ new Headers()
:
// إنشاء كائن ترويسة فارغ var headers = new Headers(); // إضافة بعض الترويسات headers.append('Content-Type', 'text/plain'); headers.append('X-My-Custom-Header', 'CustomValue'); // للترويسة set و get و check قيم headers.has('Content-Type'); // true headers.get('Content-Type'); // "text/plain" headers.set('Content-Type', 'application/json'); // حذف ترويسة headers.delete('X-My-Custom-Header'); // إضافة قيم ابتدائية var headers = new Headers({ 'Content-Type': 'text/plain', 'X-My-Custom-Header': 'CustomValue' });
يمكنك استخدام التوابع append
و has
و get
و set
و delete
لتعديل ترويسات الطلب. لاستخدام ترويسات الطلب أنشئ الكائن Request
:
var request = new Request('https://davidwalsh.name/some-url', { headers: new Headers({ 'Content-Type': 'text/plain' }) }); fetch(request).then(function() { /* معالجة الرد*/ });
لنطّلع على عمل الكائنين Response
و Request
.
الكائن Request
يمثّل الكائن Request جزء الطلب عند استدعاء التابع fetch
، يمكنك إنشاء طلبات مخصصة ومتطورة بتمرير الكائن Request
للتابع fetch
:
-
method
(الطريقة): يمكن أن تكونGET
أوPOST
أوPUT
أوDELETE
أوHEAD
-
url
(الرابط): رابط الطلب -
headers
(الترويسة): ترتبط مع الكائنHeaders
-
referrer
(المرجع): مرجع الطلب -
mode
(النمط): يكونcors
أوno-cors
أوsame-origin
-
credentials
(بيانات الاعتماد): هل تعمل ملفات تعريف الارتباط (cookies) مع الطلب؟ وتأخذ إحدى القيمتينomit
، أوsame-origin
. -
redirect
(إعادة التوجيه): يمكن أن يأخذ القيمةfollow
أوerror
أوmanual
. -
integrity
(التكامل): قيمة تكامل المصدر الفرعي. -
cache
(التخزين المؤقت): وضع التخزين المؤقت ويمكن أن يأخذ إحدى القيمdefault
أوreload
أوno-cache
عينة عن استخدام الكائنRequest
:
var request = new Request('https://davidwalsh.name/users.json', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }); // الآن استخدمه fetch(request).then(function() { /* معالجة الرد */ });
الوسيط الأول URL هو فقط الوسيط الإلزامي، وكل خاصية تصبح للقراءة فقط حالما يتم إنشاء نسخة من الكائن Request
، ومن المهم أن نلاحظ أن الكائن Request
يملك التابع clone
المهم عند استخدام fetch
ضمن الواجهة البرمجية Service Worker -- يعد الكائن Request
مجرًى ولهذا يجب أن يتم نسخه عند تمريره إلى استدعاء آخر للتابع fetch
.
بصمة التابع fetch
ولكن نفس استخدام الكائن Request
لذا يمكنك القيام بما يلي:
fetch('https://davidwalsh.name/users.json', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }).then(function() { /* معالجة الرد */ });
من المحتمل أن تستخدم نسخًا من الكائن Request
فقط ضمن Service Workers بما أن الكائن Request
والتابع fetch
يؤديان نفس الوظيفة.
الكائن Response
التابع then
الذي يخص fetch
مزود بالكائن Response
ولكن يمكنك أيضًا إنشاء كائنات Response
بنفسك -- حالة أخرى قد تواجهها عند استخدام service workers. يمكنك ضبط ما يلي عند استخدام الكائن Response
:
-
type
(النوع): يمكن أن يكون basic أو cors -
url
(الرابط) -
useFinalURL
(استخدام الرابط النهائي): قيمة منطقية للرابطurl
إذا كان رابطًا نهائيًا أم لا -
status
(الحالة): رمز الحالة (مثلًا 200، 400) -
ok
: قيمة منطقية للاستجابة الناجحة (الحالة في المجال بين 200- 299) -
statusText
(نص الحالة): نص يعبّر عن الحالة وفقًا للرمز (مثلًا: OK) -
headers
(الترويسة): كائنHeaders
المرتبط بالاستجابة
// service worker أنشئ ردك لاختبار // جديد (الجسم، الخيارات) Response كائن var response = new Response('.....', { ok: false, status: 404, url: '/' }); // Response يجلب مجدَّدًا نسخة من الكائن fetch الذي يخص then التابع fetch('https://davidwalsh.name/') .then(function(responseObj) { console.log('status: ', responseObj.status); });
يوفر الكائن Response
أيضًا التوابع التالية:
-
clone(): تُنشئ نسخة من الكائن
Response
-
()error: تعيد كائن
Response
جديد مرتبط مع خطأ في الشبكة - ()redirect: تنشئ استجابة جديدة مع رابط URL مختلف
- ()arrayBuffer: تعيد وعدًا يُقبل (resolve) مع ArrayBuffer
- ()blob: تعيد وعدًا يُقبل (resolve) مع Blob
- ()formData: تعيد وعدًا يُقبل (resolve) مع كائن FormData
- ()json: تعيد وعدًا يُقبل (resolve) مع كائن JSON
- ()text: تعيد وعدًا يُقبل (resolve) مع القيمة النصية USVString
التعامل مع JSON
بفرض أنّك أنشأت طلب لـJSON -- معلومات نتيجة ردود النداء لديها التابع json
لتحويل البيانات الخام إلى كائن جافاسكربت:
fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) { // JSON التحويل إلى return response.json(); }).then(function(j) { // هو كائن جافاسكربت j console.log(j); });
بالطبع هذا أسهل من (JSON.parse(jsonString
لكن طريقة json
تعد اختصارًا سهلًا أيضًا.
التعامل مع استجابات Text/HTML الأساسية
ليست دائما JSON هي صيغة رد الطلب المرغوبة لذا إليك كيف نجعل الاستجابة على شكل نص أو HTML:
fetch('/next/page') .then(function(response) { return response.text(); }).then(function(text) { // <!DOCTYPE .... console.log(text); });
بإمكانك الحصول على استجابة نصية عبر تسلسل طريقة then
للوعد مع طريقة text()
.
التعامل مع استجابات بشكل بيانات ثنائية
إذا كنت ترغب مثلًا بتحميل صورة باستخدام التابع fetch
فإن هذا سيكون مختلفًا.
fetch('https://davidwalsh.name/flowers.jpg') .then(function(response) { return response.blob(); }) .then(function(imageBlob) { document.querySelector('img').src = URL.createObjectURL(imageBlob); });
يأخذ التابع blob()
تدفق الاستجابة وتقرأه حتى يكتمل.
الحصول على بيانات النموذج
استخدام آخر شائع للـAJAX وهو إرسال بيانات نموذج، وإليك كيف يمكن أن نستخدم التابع fetch
للحصول على بيانات نموذج مرسلة بالطريقة POST:
fetch('https://davidwalsh.name/submit', { method: 'post', body: new FormData(document.getElementById('comment-form')) });
وإذا أردت إرسال البيانات بصيغة JSON إلى الخادم:
fetch('https://davidwalsh.name/submit-json', { method: 'post', body: JSON.stringify({ email: document.getElementById('email').value, answer: document.getElementById('answer').value }) });
سهل جدًا ومريح للعينين أيضًا.
قصة لم تُكتب
رغم أن fetch
هي واجهة برمجية سهلة الاستخدام، إلا أنّ الواجهة البرمجية الحالية -تاريخ ترجمة المقال- لا تسمح بإلغاء الطلب مما يجعلها غير مستخدمة لكثير من المطورين.
إن الواجهة البرمجية fetch
الجديدة تبدو أفضل وأسهل استخدامًا من XHR. وبعد كل ذلك تمّ إنشاؤها حتى نتمكّن من استخدام AJAX بالطريقة الصحيحة. تملك fetch
فوائد الخبرات السابقة، ولا أطيق الانتظار حتى يتم استخدامها على نطاق واسع.
ترجمة -وبتصرف- للمقال fetch API لصاحبه David Walsh
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.