تعرَّف على كيفية استخدام واجهة برمجة التطبيقات 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
). يعمل هذا الإجراء بالطريقة نفسها التي يعمل بها
استدعاء 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.