تعرَّف على كيفية استخدام 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);
وفي كل حالة من هذه الحالات، يحلّ إدخال جديد محلّ أي إدخال حالي مطابق. يستخدم هذا الإجراء قواعد المطابقة نفسها الموضّحة في القسم حول retrieving.
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
العديد من أنواع البيانات، بما في ذلك كائنات 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
لفلترة الإدخالات. لاحظ أن هذه العملية بطيئة إذا بحثت عبر مجموعات كبيرة من البيانات.
إنشاء فهرس
الطريقة الأخرى لتنفيذ البحث الخاص بك هي الاحتفاظ بفهرس منفصل للإدخالات التي يمكن البحث فيها وتخزين الفهرس في 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
بخلاف ذلك.
شكرًا
بفضل Mat Scales الذي كتب النسخة الأصلية من هذه المقالة، والتي ظهرت لأول مرة على WebFundamentals.