Tìm hiểu cách sử dụng API Bộ nhớ đệm để đặt dữ liệu ứng dụng ở chế độ có thể sử dụng khi không có mạng.
API Bộ nhớ đệm là hệ thống để lưu trữ và truy xuất các yêu cầu mạng cũng như phản hồi tương ứng. Đây có thể là các yêu cầu và phản hồi thông thường được tạo trong quá trình chạy ứng dụng hoặc có thể được tạo chỉ nhằm mục đích lưu trữ dữ liệu để sử dụng sau này.
Cache API được tạo để cho phép trình chạy dịch vụ lưu các yêu cầu mạng vào bộ nhớ đệm nhằm có thể cung cấp phản hồi nhanh, bất kể tốc độ hoặc khả năng sử dụng mạng. Tuy nhiên, API cũng có thể được sử dụng làm cơ chế lưu trữ chung.
YouTube TV có ở đâu?
API Bộ nhớ đệm có trong tất cả trình duyệt hiện đại. API này được hiển thị thông qua thuộc tính caches
chung, vì vậy, bạn có thể kiểm thử sự hiện diện của API bằng cách phát hiện tính năng đơn giản:
const cacheAvailable = 'caches' in self;
Bạn có thể truy cập vào Cache API từ cửa sổ, iframe, worker hoặc dịch vụ.
Nội dung có thể lưu trữ
Bộ nhớ đệm chỉ lưu trữ các cặp đối tượng Request
và Response
tương ứng đại diện cho yêu cầu và phản hồi HTTP. Tuy nhiên, các yêu cầu và phản hồi có thể chứa bất kỳ loại dữ liệu nào có thể được chuyển qua HTTP.
Có thể lưu trữ bao nhiêu?
Tóm lại là nhiều, ít nhất là vài trăm megabyte và có thể có hàng trăm gigabyte trở lên. Các cách triển khai trình duyệt sẽ khác nhau, nhưng dung lượng lưu trữ có sẵn thường dựa trên dung lượng lưu trữ hiện có trên thiết bị.
Tạo và mở bộ nhớ đệm
Để mở một bộ nhớ đệm, hãy dùng phương thức caches.open(name)
, truyền tên của bộ nhớ đệm dưới dạng tham số duy nhất. Nếu bộ nhớ đệm đã đặt tên không tồn tại thì bộ nhớ đệm đó sẽ được tạo. Phương thức này trả về một Promise
phân giải bằng đối tượng Cache
.
const cache = await caches.open('my-cache');
// do something with cache...
Thêm vào bộ nhớ đệm
Có 3 cách để thêm một mục vào bộ nhớ đệm – add
, addAll
và put
.
Cả 3 phương thức đều trả về một Promise
.
cache.add
Đầu tiên, có cache.add()
. Phương thức này sẽ lấy một tham số, Request
hoặc URL (string
). Tham số này gửi yêu cầu đến mạng và lưu trữ phản hồi trong bộ nhớ đệm. Nếu quá trình tìm nạp không thành công hoặc nếu mã trạng thái của phản hồi không nằm trong phạm vi 200, thì không có nội dung nào được lưu trữ và Promise
sẽ từ chối. Xin lưu ý rằng không thể lưu trữ các yêu cầu nhiều nguồn gốc không ở chế độ CORS vì các yêu cầu này trả về status
của 0
. Chỉ có thể lưu trữ những yêu cầu như vậy bằng 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
Tiếp theo là cache.addAll()
. Phương thức này hoạt động tương tự như add()
, nhưng sử dụng một mảng gồm các đối tượng hoặc URL Request
(string
). Phương thức này tương tự như việc gọi cache.add
cho từng yêu cầu riêng lẻ, ngoại trừ việc Promise
sẽ từ chối nếu có một yêu cầu nào đó không được lưu vào bộ nhớ đệm.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
Trong mỗi trường hợp này, một mục nhập mới sẽ thay thế mọi mục nhập hiện có trùng khớp. Phương thức này sử dụng cùng các quy tắc so khớp được mô tả trong phần về retrieving.
cache.put
Cuối cùng là cache.put()
, cho phép bạn lưu trữ phản hồi
từ mạng hoặc tạo và lưu trữ Response
của riêng bạn. Phương thức này có 2 tham số. Đối tượng đầu tiên có thể là đối tượng Request
hoặc URL (string
). Thứ hai phải là Response
, từ mạng hoặc do mã của bạn tạo.
// 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');
Phương thức put()
linh hoạt hơn so với add()
hoặc addAll()
và cho phép bạn lưu trữ các phản hồi không phải là CORS hoặc các phản hồi khác có mã trạng thái của phản hồi không nằm trong phạm vi 200. Thao tác này sẽ ghi đè mọi phản hồi trước đó cho cùng một yêu cầu.
Tạo đối tượng Yêu cầu
Tạo đối tượng Request
bằng URL cho nội dung đang được lưu trữ:
const request = new Request('/my-data-store/item-id');
Xử lý đối tượng Response (Phản hồi)
Hàm khởi tạo đối tượng Response
chấp nhận nhiều loại dữ liệu, bao gồm cả Blob
, ArrayBuffer
, đối tượng FormData
và chuỗi.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
Bạn có thể đặt loại MIME của Response
bằng cách đặt tiêu đề thích hợp.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
Nếu đã truy xuất Response
và muốn truy cập vào nội dung của đối tượng đó, bạn có thể sử dụng một số phương thức trợ giúp. Mỗi phần tử sẽ trả về một Promise
phân giải với giá trị thuộc một loại khác.
Phương thức | Nội dung mô tả |
---|---|
arrayBuffer |
Trả về một ArrayBuffer chứa phần nội dung, được chuyển đổi tuần tự thành các byte.
|
blob |
Trả về Blob . Nếu Response được tạo bằng Blob , thì Blob mới này cũng có cùng kiểu. Nếu không, Content-Type của Response sẽ được sử dụng.
|
text |
Diễn giải các byte của nội dung dưới dạng chuỗi được mã hoá UTF-8. |
json |
Diễn giải các byte của nội dung dưới dạng chuỗi được mã hoá UTF-8, sau đó cố gắng phân tích cú pháp chuỗi đó dưới dạng JSON. Trả về đối tượng kết quả hoặc gửi TypeError nếu không thể phân tích cú pháp chuỗi dưới dạng JSON.
|
formData |
Diễn giải các byte của nội dung dưới dạng biểu mẫu HTML, được mã hoá dưới dạng multipart/form-data hoặc application/x-www-form-urlencoded . Trả về đối tượng FormData hoặc gửi TypeError nếu không phân tích được cú pháp dữ liệu.
|
body |
Trả về một ReadableStream (có thể đọc) cho dữ liệu nội dung. |
Ví dụ
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]
Truy xuất từ bộ nhớ đệm
Để tìm một mục trong bộ nhớ đệm, bạn có thể sử dụng phương thức match
.
const response = await cache.match(request);
console.log(request, response);
Nếu request
là một chuỗi, trình duyệt sẽ chuyển đổi chuỗi đó thành Request
bằng cách gọi new Request(request)
. Hàm sẽ trả về một Promise
phân giải thành Response
nếu tìm thấy một mục trùng khớp hoặc undefined
nếu không tìm thấy mục nhập trùng khớp.
Để xác định xem hai Requests
có khớp nhau hay không, trình duyệt không chỉ dùng URL. 2 yêu cầu được coi là khác nhau nếu có các chuỗi truy vấn, tiêu đề Vary
hoặc phương thức HTTP (GET
, POST
, PUT
, v.v.) khác nhau.
Bạn có thể bỏ qua một số hoặc tất cả những điều này bằng cách truyền đối tượng tuỳ chọn dưới dạng thông số thứ hai.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
Nếu có nhiều yêu cầu đã lưu vào bộ nhớ đệm trùng khớp, thì yêu cầu được tạo đầu tiên sẽ được trả về. Nếu muốn truy xuất tất cả câu trả lời phù hợp, bạn có thể sử dụng 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.`);
Bạn có thể tìm kiếm trên tất cả bộ nhớ đệm cùng một lúc bằng cách sử dụng caches.match()
thay vì gọi cache.match()
cho mỗi bộ nhớ đệm.
Đang tìm kiếm
API Bộ nhớ đệm không cung cấp cách tìm kiếm yêu cầu hoặc phản hồi, ngoại trừ các mục nhập khớp với đối tượng Response
. Tuy nhiên, bạn có thể triển khai hoạt động tìm kiếm của riêng mình bằng cách lọc hoặc tạo chỉ mục.
Lọc
Một cách để triển khai hoạt động tìm kiếm của riêng bạn là lặp lại tất cả các mục nhập và lọc ra những mục mà bạn muốn. Giả sử bạn muốn tìm tất cả các mục có URL kết thúc bằng .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;
}
Bằng cách này, bạn có thể sử dụng bất kỳ thuộc tính nào của các đối tượng Request
và Response
để lọc các mục nhập. Lưu ý rằng quá trình này sẽ chậm nếu bạn tìm kiếm trên các tập dữ liệu lớn.
Tạo chỉ mục
Một cách khác để triển khai hoạt động tìm kiếm của riêng bạn là duy trì một chỉ mục riêng biệt gồm các mục nhập có thể tìm kiếm và lưu trữ chỉ mục trong IndexedDB. Vì đây là loại thao tác mà IndexedDB được thiết kế, nên nó có hiệu suất tốt hơn nhiều với số lượng lớn mục nhập.
Nếu lưu trữ URL của Request
cùng với các thuộc tính có thể tìm kiếm, thì bạn có thể dễ dàng truy xuất đúng mục nhập bộ nhớ đệm sau khi tìm kiếm.
Xoá một mục
Cách xoá một mục khỏi bộ nhớ đệm:
cache.delete(request);
Trong đó yêu cầu có thể là Request
hoặc chuỗi URL. Phương thức này cũng lấy đối tượng tuỳ chọn tương tự như cache.match
, cho phép bạn xoá nhiều cặp Request
/Response
cho cùng một URL.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
Xoá bộ nhớ đệm
Để xoá một bộ nhớ đệm, hãy gọi caches.delete(name)
. Hàm này trả về một Promise
phân giải thành true
nếu bộ nhớ đệm tồn tại và đã bị xoá, hoặc nếu không thì false
.
Cảm ơn bạn!
Cảm ơn Mat Scales đã viết phiên bản gốc của bài viết này, phiên bản đầu tiên xuất hiện trên Web Basicss.