واجهة برمجة تطبيقات ذاكرة التخزين المؤقت: دليل سريع

تعرَّف على كيفية استخدام Cache API لإتاحة بيانات تطبيقك بلا اتصال بالإنترنت.

cache API هي نظام لتخزين بيانات الشبكة واستردادها. والردود عليها. قد تكون هذه طلبات عادية والردود التي تم إنشاؤها أثناء تشغيل التطبيق، أو يمكنهم سيتم إنشاؤها فقط لغرض تخزين البيانات لاستخدامها في وقت لاحق.

تم إنشاء Cache API لتمكين موظفي الخدمة من تخزين طلبات الشبكة في ذاكرة التخزين المؤقت. بحيث يمكنهم تقديم استجابات سريعة، بغض النظر عن سرعة الشبكة أو مدى التوفر. ومع ذلك، يمكن أيضًا استخدام واجهة برمجة التطبيقات كآلية تخزين عامة.

أماكن توفّر المنصة

وتتوفر واجهة Cache API في جميع المتصفحات الحديثة. من المهم باستخدام السمة caches العالمية، حتى تتمكّن من إجراء اختبار لمعرفة ما إذا كان واجهة برمجة التطبيقات من خلال اكتشاف ميزات بسيطة:

const cacheAvailable = 'caches' in self;

دعم المتصفح

  • Chrome: 40.
  • الحافة: 16.
  • Firefox: 41.
  • Safari: الإصدار 11.1.

المصدر

يمكن الوصول إلى 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 (strings). هذا يعمل بشكل مشابه الاتصال بالرقم 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 أنواعًا عديدة من البيانات، بما في ذلك عناصر 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 بخلاف ذلك.

شكرًا

وبفضل مات Scales الذي كتب النسخة الأصلية من هذه المقالة، لأول مرة على WebFundamentals.