W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
把 ?ServiceWorkerModule
?導入到你的 ?AppModule
? 中不僅會注冊 Service Worker,還會提供一些服務,讓你能和 Service Worker 通訊,并控制你的應用緩存。
?SwUpdate
?服務讓你能訪問一些事件,這些事件會指出 Service Worker 何時發(fā)現(xiàn)并安裝了可用的更新
?SwUpdate
?服務支持四個獨立的操作:
?versionUpdates
?是 ?SwUpdate
?的一個 ?Observable
?屬性,并且會發(fā)出四種事件類型:
事件類型 |
詳情 |
---|---|
VersionDetectedEvent
|
當 Service Worker 在服務器上檢測到應用程序的新版本并即將開始下載時發(fā)出。 |
NoNewVersionDetectedEvent
|
當 Service Worker 檢查了服務器上應用程序的版本并且沒有找到新版本時發(fā)出。 |
VersionReadyEvent
|
當有新版本的應用程序可供客戶端激活時發(fā)出。它可用于通知用戶可用的更新或提示他們刷新頁面。 |
VersionInstallationFailedEvent
|
在新版本安裝失敗時發(fā)出。它可用于日志/監(jiān)控目的。 |
@Injectable()
export class LogUpdateService {
constructor(updates: SwUpdate) {
updates.versionUpdates.subscribe(evt => {
switch (evt.type) {
case 'VERSION_DETECTED':
console.log(`Downloading new app version: ${evt.version.hash}`);
break;
case 'VERSION_READY':
console.log(`Current app version: ${evt.currentVersion.hash}`);
console.log(`New app version ready for use: ${evt.latestVersion.hash}`);
break;
case 'VERSION_INSTALLATION_FAILED':
console.log(`Failed to install app version '${evt.version.hash}': ${evt.error}`);
break;
}
});
}
}
可以要求 Service Worker 檢查是否有任何更新已經(jīng)發(fā)布到了服務器上。Service Worker 會在初始化和每次導航請求(也就是用戶導航到應用中的另一個地址)時檢查更新。不過,如果你的站點更新非常頻繁,或者需要按計劃進行更新,你可能會選擇手動檢查更新。
通過調用 ?checkForUpdate()
? 方法來實現(xiàn):
import { ApplicationRef, Injectable } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';
import { concat, interval } from 'rxjs';
import { first } from 'rxjs/operators';
@Injectable()
export class CheckForUpdateService {
constructor(appRef: ApplicationRef, updates: SwUpdate) {
// Allow the app to stabilize first, before starting
// polling for updates with `interval()`.
const appIsStable$ = appRef.isStable.pipe(first(isStable => isStable === true));
const everySixHours$ = interval(6 * 60 * 60 * 1000);
const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$);
everySixHoursOnceAppIsStable$.subscribe(() => updates.checkForUpdate());
}
}
該方法返回一個用來表示檢查更新已經(jīng)成功完成的 ?Promise<boolean>
?。這種檢查可能會失敗,它會導致此 ?Promise
?被拒絕(reject)。
為了避免影響頁面的首次渲染,在注冊 ServiceWorker 腳本之前,?
ServiceWorkerModule
?默認會在應用程序達到穩(wěn)定態(tài)之前等待最多 30 秒。如果不斷輪詢更新(比如調用 setInterval() 或 RxJS 的 interval())就會阻止應用程序達到穩(wěn)定態(tài),則直到 30 秒結束之前都不會往瀏覽器中注冊 ServiceWorker 腳本。注意:
應用中所執(zhí)行的各種輪詢都會阻止它達到穩(wěn)定態(tài)。可以通過在開始輪詢更新之前先等應用達到穩(wěn)定態(tài)來消除這種延遲,如上述例子所示。另外,你還可以為 ServiceWorker 定義不一樣的 注冊策略。
如果當前標簽頁需要立即更新到最新的應用版本,可以通過 ?activateUpdate()
? 方法來要求立即這么做:
@Injectable()
export class PromptUpdateService {
constructor(updates: SwUpdate) {
updates.available.subscribe(event => {
if (promptUser(event)) {
updates.activateUpdate().then(() => document.location.reload());
}
});
}
}
如果調用 ?
activateUpdate()
? 而不刷新頁面,可能會破壞正在運行的應用中的惰性加載模塊,特別是如果惰性加載的模塊文件名中使用了哈希時,就會改變每一個版本。所以,建議每當 ?activateUpdate()
? 返回的 Promise 被解析時,都刷新一次頁面。
在某些情況下,Service Worker 用來為客戶端提供服務的應用版本可能處于損壞狀態(tài),如果不重新加載整個頁面,則無法恢復該狀態(tài)。
比如,設想以下情形:
index.html
?、?main.<main-hash-1>.js
? 和 ?lazy-chunk.<lazy-hash-1>.js
?。index.html
?、?main.<main-hash-2>.js
? 和 ?lazy-chunk.<lazy-hash-2>.js
?。注意:
哈希值現(xiàn)在已經(jīng)不同了,因為文件的內(nèi)容已經(jīng)改變)。服務器上不再提供舊版本。
舊版本在服務器上不再可用。
lazy-chunk.<lazy-hash-1>.js
? 瀏覽器可能決定從緩存中清退特定(或所有)資源,以便回收磁盤空間。
index.html
? 和 ?main.<main-hash-1>.js
?)。
lazy-chunk.<lazy-hash-1>.js
?。
lazy-chunk.<lazy-hash-2>.js
?)。在上述情況下,Service Worker 將無法提供通常會被緩存的資產(chǎn)。該特定的應用程序版本已損壞,并且無法在不重新加載頁面的情況下修復客戶端的狀態(tài)。在這種情況下,Service Worker 會通過發(fā)送 ?UnrecoverableStateEvent
?事件來通知客戶端??梢杂嗛?nbsp;?SwUpdate#unrecoverable
? 以得到通知并處理這些錯誤。
@Injectable()
export class HandleUnrecoverableStateService {
constructor(updates: SwUpdate) {
updates.unrecoverable.subscribe(event => {
notifyUser(
'An error occurred that we cannot recover from:\n' +
event.reason +
'\n\nPlease reload the page.'
);
});
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: