Vào năm 2015, chúng tôi giới thiệu tính năng Đồng bộ hoá trong nền, cho phép service worker để trì hoãn công việc cho đến khi người dùng có kết nối. Điều này có nghĩa là người dùng có thể nhập tin nhắn, nhấn gửi và rời khỏi trang web khi biết rằng tin nhắn sẽ được gửi ngay bây giờ hoặc khi nào có kết nối.
Đây là một tính năng hữu ích, nhưng nó đòi hỏi trình chạy dịch vụ phải tồn tại trong suốt thời gian tìm nạp. Đó không phải là vấn đề đối với các công việc ngắn như gửi tin nhắn, nhưng nếu tác vụ mất nhiều thời gian quá lâu thì trình duyệt sẽ tắt worker dịch vụ, nếu không sẽ gây rủi ro cho quyền riêng tư và pin.
Vậy nếu bạn cần tải nội dung nào đó có thể mất nhiều thời gian, chẳng hạn như phim, podcast hoặc của một trò chơi. Đó chính là mục đích của tính năng Tìm nạp trong nền.
Tính năng Tìm nạp trong nền được cung cấp theo mặc định kể từ Chrome 74.
Dưới đây là bản minh hoạ nhanh dài 2 phút cho thấy trạng thái truyền thống so với cách sử dụng Tìm nạp trong nền:
Tự dùng thử bản minh hoạ và duyệt xem mã.
Cách hoạt động
Thao tác tìm nạp ở chế độ nền hoạt động như sau:
- Bạn yêu cầu trình duyệt thực hiện một nhóm các lần tìm nạp trong nền.
- Trình duyệt sẽ tìm nạp những thông tin đó và hiển thị tiến trình cho người dùng.
- Sau khi tìm nạp xong hoặc không thành công, trình duyệt sẽ mở trình chạy dịch vụ của bạn và kích hoạt một sự kiện để cho bạn biết những gì đã xảy ra. Đây là nơi bạn quyết định sẽ làm gì với các câu trả lời, nếu có.
Nếu người dùng đóng các trang trong trang web của bạn sau bước 1 thì quá trình tải xuống sẽ tiếp tục. Bởi vì quá trình tìm nạp có thể nhìn thấy rõ ràng và dễ dàng bị huỷ bỏ, thời gian quá dài cũng không phải là lo ngại về quyền riêng tư tác vụ đồng bộ hoá ở chế độ nền. Do trình chạy dịch vụ không liên tục chạy nên không phải lo lắng nó có thể lạm dụng hệ thống, chẳng hạn như đào bitcoin trong nền.
Trên một số nền tảng (chẳng hạn như Android), trình duyệt có thể đóng sau bước 1, vì trình duyệt có thể chuyển việc tìm nạp sang hệ điều hành.
Nếu người dùng bắt đầu tải xuống khi không có mạng hoặc không có kết nối mạng trong khi tải xuống, thì chế độ nền tìm nạp sẽ bị tạm dừng và tiếp tục sau đó.
API
Phát hiện tính năng
Giống như bất kỳ tính năng mới nào, bạn đều muốn biết trình duyệt có hỗ trợ tính năng đó hay không. Đối với Tìm nạp trong nền, đó là đơn giản như:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Bắt đầu tìm nạp ở chế độ nền
API chính sẽ ngừng đăng ký service worker, vì vậy, hãy đảm bảo bạn đã đăng ký service worker trước. Sau đó:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.fetch('my-fetch', ['/ep-5.mp3', 'ep-5-artwork.jpg'], {
title: 'Episode 5: Interesting things.',
icons: [{
sizes: '300x300',
src: '/ep-5-icon.png',
type: 'image/png',
}],
downloadTotal: 60 * 1024 * 1024,
});
});
backgroundFetch.fetch
nhận 3 đối số:
Thông số | |
---|---|
id |
string xác định duy nhất lần tìm nạp trong nền này.
|
requests |
Array<Request|string>
Nội dung cần tìm nạp. Chuỗi sẽ được coi là URL và được chuyển thành Request qua new Request(theString) .
Bạn có thể tìm nạp thông tin từ các nguồn khác, miễn là các tài nguyên đó cho phép việc này qua CORS. Lưu ý: Chrome hiện không hỗ trợ các yêu cầu cần có quy trình kiểm tra CORS. |
options |
Một đối tượng có thể bao gồm: |
options.title |
string Tiêu đề cho trình duyệt hiển thị cùng với tiến trình. |
options.icons |
Array<IconDefinition> Một mảng đối tượng có "src", "size" và "type". |
options.downloadTotal |
number Tổng kích thước của nội dung phản hồi (sau khi được giải nén). Mặc dù không bắt buộc nhưng bạn nên cung cấp thông tin này. Thông tin này được dùng để cho biết cho người dùng về kích thước của tệp tải xuống cũng như để cung cấp thông tin về tiến trình. Nếu bạn không cung cấp điều này, trình duyệt sẽ cho người dùng biết kích thước không xác định và do đó người dùng có thể có thể huỷ quá trình tải xuống. Nếu số lượt tải xuống tìm nạp ở chế độ nền vượt quá số lượng được cung cấp ở đây, thì lượt tải xuống này sẽ bị huỷ. Bây giờ
hoàn toàn không có vấn đề gì nếu tệp tải xuống nhỏ hơn |
backgroundFetch.fetch
trả về lời hứa phân giải bằng BackgroundFetchRegistration
. Tôi sẽ
tôi sẽ trình bày chi tiết về vấn đề đó ở phần sau. Lời hứa sẽ từ chối nếu người dùng đã chọn không tải xuống hoặc
trong số các thông số đã cho không hợp lệ.
Việc cung cấp nhiều yêu cầu cho một lần tìm nạp ở chế độ nền cho phép bạn kết hợp mọi thứ theo logic đối với người dùng. Ví dụ: một bộ phim có thể được chia thành 1.000 tài nguyên (thông thường với MPEG-DASH), và đi kèm với các tài nguyên bổ sung như hình ảnh. Một cấp độ của trò chơi có thể được trải rộng trên nhiều Tài nguyên JavaScript, hình ảnh và âm thanh. Nhưng với người dùng, đó chỉ là "bộ phim", hay "cấp độ".
Lấy thao tác tìm nạp ở chế độ nền hiện có
Bạn có thể sử dụng phương thức tìm nạp trong nền hiện có như sau:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
...bằng cách truyền id (mã nhận dạng) của lần tìm nạp dữ liệu nền mà bạn muốn. get
sẽ trả về undefined
nếu không có
đang hoạt động tìm nạp nền bằng ID đó.
Quá trình tìm nạp ở chế độ nền được coi là "đang hoạt động" từ thời điểm đăng ký cho đến khi thành công, không thành công hoặc bị huỷ bỏ.
Bạn có thể nhận danh sách tất cả các lần tìm nạp ở chế độ nền đang hoạt động bằng cách sử dụng getIds
:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
Lượt đăng ký tìm nạp ở chế độ nền
BackgroundFetchRegistration
(bgFetch
trong các ví dụ trên) có những phần tử sau:
Thuộc tính | |
---|---|
id |
string Mã nhận dạng của lần tìm nạp ở chế độ nền. |
uploadTotal |
number Số byte sẽ được gửi đến máy chủ. |
uploaded |
number Số byte đã gửi thành công. |
downloadTotal |
number Giá trị được cung cấp khi tìm nạp ở chế độ nền được đăng ký, hoặc 0. |
downloaded |
number Số byte đã nhận thành công. Giá trị này có thể giảm. Ví dụ: nếu kết nối bị mất và không thể tải xuống được tiếp tục, trong trường hợp này trình duyệt sẽ khởi động lại quá trình tìm nạp cho tài nguyên đó từ đầu. |
result |
Một trong số sau:
|
failureReason |
Một trong số sau:
|
recordsAvailable |
boolean Có thể truy cập vào các yêu cầu/phản hồi cơ bản không? Khi giá trị này là false, thì bạn không thể dùng |
Phương thức | |
abort() |
Trả về Promise<boolean> Huỷ thao tác tìm nạp ở chế độ nền. Lời hứa được trả về sẽ phân giải bằng giá trị true nếu quá trình tìm nạp bị huỷ thành công. |
matchAll(request, opts) |
Trả về Promise<Array<BackgroundFetchRecord>> Nhận yêu cầu và phản hồi. Các đối số ở đây giống như bộ nhớ đệm . Việc gọi mà không có đối số sẽ trả về hứa hẹn cho tất cả bản ghi. Hãy xem mục bên dưới để biết thêm thông tin. |
match(request, opts) |
Trả về Promise<BackgroundFetchRecord> Như trên, nhưng phân giải bằng trận đấu đầu tiên. |
Sự kiện | |
progress |
Được kích hoạt khi có bất kỳ giá trị nào trong số uploaded , downloaded , result hoặc
Đã thay đổi failureReason . |
Đang theo dõi tiến trình
Bạn có thể thực hiện việc này thông qua sự kiện progress
. Hãy nhớ rằng downloadTotal
là bất kỳ giá trị nào mà bạn
đã cung cấp hoặc 0
nếu bạn không cung cấp giá trị.
bgFetch.addEventListener('progress', () => {
// If we didn't provide a total, we can't provide a %.
if (!bgFetch.downloadTotal) return;
const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
console.log(`Download progress: ${percent}%`);
});
Nhận yêu cầu và phản hồi
bgFetch.match('/ep-5.mp3').then(async (record) => {
if (!record) {
console.log('No record found');
return;
}
console.log(`Here's the request`, record.request);
const response = await record.responseReady;
console.log(`And here's the response`, response);
});
record
là một BackgroundFetchRecord
và có dạng như sau:
Thuộc tính | |
---|---|
request |
Request Yêu cầu được đưa ra. |
responseReady |
Promise<Response> Phản hồi được tìm nạp. Câu trả lời được thực hiện dựa trên một lời hứa vì có thể chưa nhận được. Lời hứa sẽ từ chối nếu tìm nạp không thành công. |
Sự kiện của trình chạy dịch vụ
Sự kiện | |
---|---|
backgroundfetchsuccess |
Đã tìm nạp xong mọi thứ. |
backgroundfetchfailure |
Một hoặc nhiều lần tìm nạp không thành công. |
backgroundfetchabort |
Một hoặc nhiều lần tìm nạp không thành công.
Điều này chỉ thực sự hữu ích nếu bạn muốn xoá các dữ liệu có liên quan. |
backgroundfetchclick |
Người dùng nhấp vào giao diện người dùng về tiến trình tải xuống. |
Các đối tượng sự kiện có như sau:
Thuộc tính | |
---|---|
registration |
BackgroundFetchRegistration |
Phương thức | |
updateUI({ title, icons }) |
Cho phép bạn thay đổi tiêu đề/biểu tượng bạn đặt ban đầu. Đây là thao tác không bắt buộc, nhưng cho phép bạn
cung cấp thêm ngữ cảnh nếu cần. Bạn chỉ có thể thực hiện việc này *một lần* trong thời gian
backgroundfetchsuccess và backgroundfetchfailure sự kiện. |
Phản ứng với thành công/thất bại
Chúng ta đã thấy sự kiện progress
, nhưng sự kiện này chỉ hữu ích khi người dùng có một trang đang mở
trang web của bạn. Lợi ích chính của tính năng tìm nạp trong nền là mọi thứ tiếp tục hoạt động sau khi người dùng rời khỏi
hoặc thậm chí đóng trình duyệt.
Nếu quá trình tìm nạp trong nền hoàn tất thành công, trình chạy dịch vụ của bạn sẽ nhận được
Sự kiện backgroundfetchsuccess
và event.registration
sẽ là hoạt động đăng ký tìm nạp ở chế độ nền.
Sau sự kiện này, bạn sẽ không thể truy cập vào các yêu cầu và phản hồi đã tìm nạp được nữa. Vì vậy, nếu muốn giữ lại chúng, hãy di chuyển chúng đến một nơi nào đó như API bộ nhớ đệm.
Tương tự như với hầu hết các sự kiện của trình chạy dịch vụ, hãy sử dụng event.waitUntil
để trình chạy dịch vụ biết thời điểm xảy ra sự kiện
đã hoàn tất.
Ví dụ như trong trình chạy dịch vụ:
addEventListener('backgroundfetchsuccess', (event) => {
const bgFetch = event.registration;
event.waitUntil(async function() {
// Create/open a cache.
const cache = await caches.open('downloads');
// Get all the records.
const records = await bgFetch.matchAll();
// Copy each request/response across.
const promises = records.map(async (record) => {
const response = await record.responseReady;
await cache.put(record.request, response);
});
// Wait for the copying to complete.
await Promise.all(promises);
// Update the progress notification.
event.updateUI({ title: 'Episode 5 ready to listen!' });
}());
});
Lỗi có thể là lỗi 404. Lỗi này có thể không quan trọng với bạn, vì vậy có thể bạn vẫn nên sao chép một số phản hồi vào bộ nhớ đệm như trên.
Thể hiện cảm xúc khi nhấp vào
Giao diện người dùng hiển thị tiến trình và kết quả tải xuống có thể nhấp vào. Sự kiện backgroundfetchclick
ở
service worker cho phép bạn phản ứng với điều này. Như trên, event.registration
sẽ là nền
đăng ký tìm nạp.
Việc phổ biến cần làm với sự kiện này là mở một cửa sổ:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
Tài nguyên khác
Đính chính: Phiên bản trước của bài viết này đã nhầm lẫn về việc Tìm nạp trong nền là một "tiêu chuẩn web". API này hiện không thuộc kênh tiêu chuẩn. Bạn có thể xem quy cách trên WICG dưới dạng Báo cáo dự thảo của nhóm cộng đồng.