เรียนรู้วิธีใช้ API แคชเพื่อทำให้ข้อมูลแอปพลิเคชันของคุณใช้งานแบบออฟไลน์ได้
Cache API คือระบบสำหรับจัดเก็บและเรียกข้อมูลเครือข่าย และการตอบกลับที่เกี่ยวข้อง นี่อาจเป็นคำขอทั่วไป และคำตอบที่สร้างขึ้นในระหว่างการใช้งานแอปพลิเคชัน หรือสามารถ สร้างขึ้นเพื่อจุดประสงค์ในการจัดเก็บข้อมูลไว้ใช้ในภายหลังเท่านั้น
สร้าง Cache API เพื่อเปิดใช้ Service Worker เพื่อแคชคำขอเครือข่าย เพื่อให้ตอบสนองได้อย่างรวดเร็ว ไม่ว่าจะมีความเร็วเครือข่ายหรือ อย่างไรก็ตาม API ยังสามารถใช้เป็นกลไกการจัดเก็บข้อมูลทั่วไปได้
พร้อมให้บริการที่ไหนบ้าง
API แคชมีอยู่ในเบราว์เซอร์รุ่นใหม่ทั้งหมด ใช่เลย
ผ่านพร็อพเพอร์ตี้ caches
ทั่วโลกเพื่อให้คุณทดสอบการแสดง
API ที่มีการตรวจหาคุณลักษณะง่ายๆ ดังนี้
const cacheAvailable = 'caches' in self;
คุณสามารถเข้าถึง Cache API ได้จากหน้าต่าง, iframe, Worker หรือ Service Worker
ข้อมูลที่จัดเก็บได้
แคชจะจัดเก็บเฉพาะคู่ของ Request
และ
ออบเจ็กต์ Response
ซึ่งแสดงคำขอ HTTP และการตอบกลับ
ตามลำดับ แต่คำขอและการตอบกลับอาจมีข้อมูลประเภทใดก็ได้
ซึ่งสามารถโอนผ่าน HTTP ได้
คุณจะจัดเก็บได้มากแค่ไหน
กล่าวโดยสรุปคือมาก อย่างน้อย 2-3 เมกะไบต์ และ หลายร้อยกิกะไบต์หรือมากกว่า การใช้งานเบราว์เซอร์จะแตกต่างกันไป แต่จำนวน โดยปกติ พื้นที่เก็บข้อมูลที่ใช้ได้จะขึ้นอยู่กับปริมาณพื้นที่เก็บข้อมูลที่มีใน อุปกรณ์
การสร้างและเปิดแคช
หากต้องการเปิดแคช ให้ใช้เมธอด caches.open(name)
โดยส่งชื่อของ
เป็นพารามิเตอร์เดียว ถ้าไม่มีแคชที่มีชื่อ ชื่อดังกล่าวคือ
สร้าง แล้ว เมธอดนี้จะแสดง Promise
ที่แก้ไขด้วยออบเจ็กต์ Cache
const cache = await caches.open('my-cache');
// do something with cache...
กำลังเพิ่มลงในแคช
การเพิ่มรายการไปยังแคชทำได้ 3 วิธี ได้แก่ add
, addAll
และ put
ทั้ง 3 วิธีจะแสดงผล Promise
cache.add
รายการแรกคือ cache.add()
ต้องใช้พารามิเตอร์ 1 รายการ ซึ่งอาจเป็น 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()
แต่ใช้เวลา
อาร์เรย์ของออบเจ็กต์หรือ URL Request
รายการ (string
) วิธีนี้ทำงานคล้ายกับ
โทรหา cache.add
สำหรับคำขอแต่ละรายการ ยกเว้นว่า Promise
ปฏิเสธหากไม่มีแคชคำขอรายการเดียว
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
ในแต่ละกรณีเหล่านี้ รายการใหม่จะเขียนทับรายการที่มีอยู่ที่ตรงกัน ซึ่งใช้กฎการจับคู่ที่ตรงกันเดียวกับที่อธิบายในหัวข้อ การดึงข้อมูล
cache.put
สุดท้ายคือ cache.put()
ซึ่งให้คุณเก็บคำตอบ
จากเครือข่าย หรือสร้างและจัดเก็บ Response
ของคุณเอง ต้องใช้ 2
พารามิเตอร์ รายการแรกอาจเป็นออบเจ็กต์ Request
หรือ URL (string
) ก็ได้
รายการที่ 2 ต้องเป็น 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
2 รายการตรงกันหรือไม่ เบราว์เซอร์จะใช้มากกว่าแค่ URL 2 อย่าง
จะถือว่าคำขอต่างกันหากมีสตริงการค้นหาต่างกัน
ส่วนหัว Vary
หรือเมธอด HTTP (GET
, POST
, PUT
ฯลฯ)
คุณสามารถเพิกเฉยต่อสิ่งเหล่านี้ทั้งหมดหรือบางส่วนได้โดยการส่งผ่านออบเจ็กต์ตัวเลือก พารามิเตอร์ที่ 2
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
ถ้าคำขอที่แคชไว้มากกว่า 1 รายการตรงกัน คำขอที่สร้างขึ้นก่อนจะเป็น
ส่งคืนแล้ว ถ้าต้องการเรียกคำตอบที่ตรงกันทั้งหมด คุณสามารถใช้
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()
สำหรับแต่ละแคช
กำลังค้นหา
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