تعرَّف على كيفية استخدام واجهة برمجة التطبيقات Cache API لتوفير بيانات تطبيقك بلا اتصال بالإنترنت.
Cache API هي نظام لتخزين واسترداد طلبات الشبكة والردود المقابلة لها. وقد تكون هذه طلبات وردودًا منتظمة يتم إنشاؤها أثناء تشغيل تطبيقك، أو يمكن إنشاؤها فقط بغرض تخزين البيانات لاستخدامها في وقت لاحق.
تم إنشاء واجهة برمجة التطبيقات Cache API لتمكين موظفي الخدمة من تخزين طلبات الشبكة في ذاكرة التخزين المؤقت بحيث يمكنهم تقديم ردود سريعة، بغض النظر عن سرعة الشبكة أو توفّرها. ومع ذلك، يمكن أيضًا استخدام واجهة برمجة التطبيقات كآلية تخزين عامة.
أماكن توفّر المنصة
تتوفّر واجهة برمجة التطبيقات Cache API في جميع المتصفحات الحديثة. ويتم عرضها
من خلال الموقع الشامل caches
، ما يتيح لك اختبار توفّر
واجهة برمجة التطبيقات باستخدام ميزة رصد بسيطة:
const cacheAvailable = 'caches' in self;
يمكن الوصول إلى واجهة برمجة التطبيقات Cache API من نافذة أو إطار iframe أو عامل أو مشغّل خدمات.
المحتوى الذي يمكن تخزينه
لا تخزِّن ذاكرات التخزين المؤقت سوى أزواج من كائنَي Request
و
Response
، اللذين يمثّلان طلبات HTTP واستجاباتها،
على التوالي. ومع ذلك، يمكن أن تحتوي الطلبات والردود على أي نوع من البيانات
التي يمكن نقلها عبر بروتوكول HTTP.
ما هو الحد الأقصى المسموح به للتخزين؟
باختصار، الكثير، أي ما لا يقل عن بضع مئات من الميغابايت، وقد يصل إلى مئات الغيغابايت أو أكثر. تختلف عمليات تنفيذ المتصفّحات، ولكن تستند عادةً كمية مساحة التخزين المتوفّرة إلى كمية مساحة التخزين المتوفّرة على الجهاز.
إنشاء ذاكرة تخزين مؤقت وفتحها
لفتح ذاكرة تخزين مؤقت، استخدِم الطريقة caches.open(name)
مع إدخال اسم ذاكرة التخزين المؤقت كمعلّمة واحدة. إذا لم تكن ذاكرة التخزين المؤقت المُسمّاة متوفّرة، يتم
إنشاؤها. تُرجع هذه الطريقة Promise
يتم حلّه باستخدام عنصر Cache
.
const cache = await caches.open('my-cache');
// do something with cache...
الإضافة إلى ذاكرة تخزين مؤقت
هناك ثلاث طرق لإضافة عنصر إلى ذاكرة تخزين مؤقت - add
وaddAll
وput
.
تعرض الطرق الثلاث Promise
.
cache.add
أولاً، هناك cache.add()
. يأخذ هذا الإجراء مَعلمة واحدة، إما Request
أو عنوان URL (string
). ويُقدّم طلبًا إلى الشبكة ويخزّن الردّ
في ذاكرة التخزين المؤقت. إذا تعذّر
الاسترداد أو إذا لم يكن رمز حالة الاستجابة ضمن النطاق 200،
لن يتم تخزين أي بيانات وسيتم رفض Promise
. يُرجى العِلم أنّه لا يمكن تخزين طلبات
المرسَلة من مصادر مختلفة والتي لا تعمل في وضع CORS لأنّها تعرض status
من
0
. لا يمكن تخزين هذه الطلبات إلا باستخدام put
.
// Retreive data.json from the server and store the response.
cache.add(new Request('/data.json'));
// Retreive data.json from the server and store the response.
cache.add('/data.json');
cache.addAll
بعد ذلك، هناك cache.addAll()
. وهي تعمل بشكل مشابه لـ add()
، ولكنها تأخذ مصفوفة من كائنات Request
أو عناوين URL (string
s). يعمل هذا الإجراء بالطريقة نفسها التي يعمل بها
استدعاء cache.add
لكل طلب فردي، باستثناء أنّ Promise
يرفض الطلب إذا لم يتم تخزين أي طلب فردي في ذاكرة التخزين المؤقت.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
في كلّ من هذه الحالات، يحلّ الإدخال الجديد محلّ أيّ إدخال حالي مطابق. ويستخدم هذا الإجراء قواعد المطابقة نفسها الموضّحة في قسم الاسترداد.
cache.put
وأخيرًا، هناك cache.put()
، الذي يتيح لك تخزين إما رد
من الشبكة أو إنشاء Response
خاص بك وتخزينه. تستغرق هذه العملية مَعلمتَين. يمكن أن يكون العنصر الأول عنصرًا من النوع Request
أو عنوان URL (string
).
يجب أن يكون العنصر الثاني من النوع Response
، إما من الشبكة أو تم إنشاؤه باستخدام
الرمز.
// Retrieve data.json from the server and store the response.
cache.put('/data.json');
// Create a new entry for test.json and store the newly created response.
cache.put('/test.json', new Response('{"foo": "bar"}'));
// Retrieve data.json from the 3rd party site and store the response.
cache.put('https://example.com/data.json');
إنّ طريقة put()
أكثر تساهلاً من add()
أو addAll()
وستسمح لك بتخزين الاستجابات غير المستندة إلى سياسة مشاركة الموارد المتعددة المصادر (CORS) أو الاستجابات الأخرى التي لا يكون فيها رمز الحالة للاستجابة ضمن النطاق 200. وسيؤدي ذلك إلى استبدال أي ردود سابقة
للطلب نفسه.
إنشاء عناصر "الطلبات"
أنشئ عنصر Request
باستخدام عنوان URL للعنصر الذي يتم تخزينه:
const request = new Request('/my-data-store/item-id');
العمل مع عناصر Response
تقبل الدالة الإنشائية للكائن Response
العديد من أنواع البيانات، بما في ذلك كائنات Blob
وArrayBuffer
وFormData
والسلاسل.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
يمكنك ضبط نوع MIME لـ Response
من خلال ضبط العنوان المناسب.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
إذا استعدت Response
وأردت الوصول إلى نصه، يمكنك اتّباع عدة طرق مساعِدة. ويعرِض كلّ منها Promise
يتمّ حلّه
بقيمة من نوع مختلف.
الطريقة | الوصف |
---|---|
arrayBuffer |
تعرِض هذه الدالة ArrayBuffer يحتوي على النص، ويتم تسلسله إلى
وحدات البايت.
|
blob |
عرض Blob إذا تم إنشاء Response
باستخدام Blob ، سيكونBlob الجديد من النوع
نفسه. وبخلاف ذلك، يتم استخدام Content-Type
من Response .
|
text |
يفسّر وحدات بايت النص كسلسلة مرمّزة بترميز UTF-8. |
json |
تفسِّر وحدات البايت في النصّ على أنّها سلسلة بترميز UTF-8، ثم تحاول
تحليلها بتنسيق JSON. تُرجِع هذه الدالة الكائن الناتج، أو تُعرِض خطأ
TypeError إذا تعذّر تحليل السلسلة كملف JSON.
|
formData |
يفسّر وحدات بايت النص الأساسي كنموذج HTML، مرمّزًا إما على هيئة multipart/form-data أو application/x-www-form-urlencoded . تعرض كائن
FormData
أو تطرح TypeError إذا تعذّر تحليل البيانات.
|
body |
تعرِض ReadableStream لبيانات الجسم. |
على سبيل المثال:
const response = new Response('Hello world');
const buffer = await response.arrayBuffer();
console.log(new Uint8Array(buffer));
// Uint8Array(11) [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
الاسترداد من ذاكرة تخزين مؤقت
للعثور على عنصر في ذاكرة التخزين المؤقت، يمكنك استخدام الطريقة match
.
const response = await cache.match(request);
console.log(request, response);
إذا كان request
سلسلة، يحوّلها المتصفّح إلى Request
من خلال استدعاء
new Request(request)
. تُرجع الدالة Promise
الذي يُحلّ إلى
Response
إذا تم العثور على إدخال مطابق، أو undefined
في الحالات الأخرى.
لتحديد ما إذا كان هناك تطابق بين Requests
، يستخدم المتصفّح أكثر من عنوان URL فقط. يُعتبَر طلبان مختلفَين إذا كانا يتضمّنان سلاسل طلبات بحث مختلفة أو عناوين Vary
أو طرق HTTP مختلفة (GET
أو POST
أو PUT
أو غير ذلك).
يمكنك تجاهل بعض هذه العناصر أو جميعها من خلال تمرير عنصر خيارات كسمة ثانية.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
إذا تطابق أكثر من طلب واحد مخزّن مؤقتًا، يتم عرض الطلب الذي تم إنشاؤه أولاً. إذا أردت استرداد جميع الردود المطابقة، يمكنك استخدام
cache.matchAll()
.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const responses = await cache.matchAll(request, options);
console.log(`There are ${responses.length} matching responses.`);
كاختصار، يمكنك البحث في جميع ذاكرات التخزين المؤقت في آنٍ واحد باستخدام caches.match()
بدلاً من استدعاء cache.match()
لكل ذاكرة تخزين مؤقت.
جارٍ البحث
لا توفّر واجهة برمجة التطبيقات Cache API طريقة للبحث عن الطلبات أو الردود
باستثناء مطابقة الإدخالات مع عنصر Response
. مع ذلك، يمكنك تنفيذ بحثك الخاص باستخدام الفلترة أو إنشاء فهرس.
الفلترة
من إحدى الطرق لتنفيذ عملية البحث الخاصة بك هي تكرار جميع الإدخالات
والفلترة للوصول إلى الإدخالات التي تريدها. لنفترض أنّك تريد العثور على كل
العناصر التي تحتوي على عناوين URL تنتهي بـ .png
.
async function findImages() {
// Get a list of all of the caches for this origin
const cacheNames = await caches.keys();
const result = [];
for (const name of cacheNames) {
// Open the cache
const cache = await caches.open(name);
// Get a list of entries. Each item is a Request object
for (const request of await cache.keys()) {
// If the request URL matches, add the response to the result
if (request.url.endsWith('.png')) {
result.push(await cache.match(request));
}
}
}
return result;
}
بهذه الطريقة، يمكنك استخدام أيّ سمة من سمات العنصرَين Request
وResponse
لfiltrare الإدخالات. لاحظ أن هذه العملية بطيئة إذا بحثت عبر مجموعات كبيرة من البيانات.
إنشاء فهرس
الطريقة الأخرى لتنفيذ البحث الخاص بك هي الاحتفاظ بفهرس منفصل للإدخالات التي يمكن البحث فيها وتخزين الفهرس في IndexedDB. وبما أنّ هذا هو نوع العملية التي تم تصميم IndexedDB من أجلها، فإنّ أدائها أفضل بكثير مع أعداد كبيرة من الإدخالات.
إذا خزّنت عنوان URL الخاص بالسمة Request
مع السمات القابلة للبحث،
يمكنك بسهولة استرداد إدخال ذاكرة التخزين المؤقت الصحيح بعد إجراء البحث.
حذف عنصر
لحذف عنصر من ذاكرة التخزين المؤقت:
cache.delete(request);
حيث يمكن أن يكون الطلب Request
أو سلسلة عنوان URL. تستخدِم هذه الطريقة أيضًا
عنصر الخيارات نفسه المستخدَم في cache.match
، ما يتيح لك حذف عدة تربُّعات
Request
/Response
لعنوان URL نفسه.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
حذف ذاكرة تخزين مؤقت
لحذف ذاكرة تخزين مؤقت، اتصل على caches.delete(name)
. تعرض هذه الدالة قيمة
Promise
التي تؤدي إلى true
إذا كانت ذاكرة التخزين المؤقت متوفّرة وتم حذفها، أو
false
في الحالات الأخرى.
شكرًا
نشكر "مات سكيلز" الذي كتب النسخة الأصلية من هذه المقالة، والتي ظهرت لأول مرة على WebFundamentals.