W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
把 ?ServiceWorkerModule
?導(dǎo)入到你的 ?AppModule
? 中不僅會(huì)注冊(cè) Service Worker,還會(huì)提供一些服務(wù),讓你能和 Service Worker 通訊,并控制你的應(yīng)用緩存。
?SwUpdate
?服務(wù)讓你能訪問(wèn)一些事件,這些事件會(huì)指出 Service Worker 何時(shí)發(fā)現(xiàn)并安裝了可用的更新
?SwUpdate
?服務(wù)支持四個(gè)獨(dú)立的操作:
?versionUpdates
?是 ?SwUpdate
?的一個(gè) ?Observable
?屬性,并且會(huì)發(fā)出四種事件類型:
事件類型 |
詳情 |
---|---|
VersionDetectedEvent
|
當(dāng) Service Worker 在服務(wù)器上檢測(cè)到應(yīng)用程序的新版本并即將開始下載時(shí)發(fā)出。 |
NoNewVersionDetectedEvent
|
當(dāng) Service Worker 檢查了服務(wù)器上應(yīng)用程序的版本并且沒(méi)有找到新版本時(shí)發(fā)出。 |
VersionReadyEvent
|
當(dāng)有新版本的應(yīng)用程序可供客戶端激活時(shí)發(fā)出。它可用于通知用戶可用的更新或提示他們刷新頁(yè)面。 |
VersionInstallationFailedEvent
|
在新版本安裝失敗時(shí)發(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ā)布到了服務(wù)器上。Service Worker 會(huì)在初始化和每次導(dǎo)航請(qǐng)求(也就是用戶導(dǎo)航到應(yīng)用中的另一個(gè)地址)時(shí)檢查更新。不過(guò),如果你的站點(diǎn)更新非常頻繁,或者需要按計(jì)劃進(jìn)行更新,你可能會(huì)選擇手動(dòng)檢查更新。
通過(guò)調(diào)用 ?checkForUpdate()
? 方法來(lái)實(shí)現(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());
}
}
該方法返回一個(gè)用來(lái)表示檢查更新已經(jīng)成功完成的 ?Promise<boolean>
?。這種檢查可能會(huì)失敗,它會(huì)導(dǎo)致此 ?Promise
?被拒絕(reject)。
為了避免影響頁(yè)面的首次渲染,在注冊(cè) ServiceWorker 腳本之前,?
ServiceWorkerModule
?默認(rèn)會(huì)在應(yīng)用程序達(dá)到穩(wěn)定態(tài)之前等待最多 30 秒。如果不斷輪詢更新(比如調(diào)用 setInterval() 或 RxJS 的 interval())就會(huì)阻止應(yīng)用程序達(dá)到穩(wěn)定態(tài),則直到 30 秒結(jié)束之前都不會(huì)往瀏覽器中注冊(cè) ServiceWorker 腳本。注意:
應(yīng)用中所執(zhí)行的各種輪詢都會(huì)阻止它達(dá)到穩(wěn)定態(tài)。可以通過(guò)在開始輪詢更新之前先等應(yīng)用達(dá)到穩(wěn)定態(tài)來(lái)消除這種延遲,如上述例子所示。另外,你還可以為 ServiceWorker 定義不一樣的 注冊(cè)策略。
如果當(dāng)前標(biāo)簽頁(yè)需要立即更新到最新的應(yīng)用版本,可以通過(guò) ?activateUpdate()
? 方法來(lái)要求立即這么做:
@Injectable()
export class PromptUpdateService {
constructor(updates: SwUpdate) {
updates.available.subscribe(event => {
if (promptUser(event)) {
updates.activateUpdate().then(() => document.location.reload());
}
});
}
}
如果調(diào)用 ?
activateUpdate()
? 而不刷新頁(yè)面,可能會(huì)破壞正在運(yùn)行的應(yīng)用中的惰性加載模塊,特別是如果惰性加載的模塊文件名中使用了哈希時(shí),就會(huì)改變每一個(gè)版本。所以,建議每當(dāng) ?activateUpdate()
? 返回的 Promise 被解析時(shí),都刷新一次頁(yè)面。
在某些情況下,Service Worker 用來(lái)為客戶端提供服務(wù)的應(yīng)用版本可能處于損壞狀態(tài),如果不重新加載整個(gè)頁(yè)面,則無(wú)法恢復(fù)該狀態(tài)。
比如,設(shè)想以下情形:
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)不同了,因?yàn)槲募膬?nèi)容已經(jīng)改變)。服務(wù)器上不再提供舊版本。
舊版本在服務(wù)器上不再可用。
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 將無(wú)法提供通常會(huì)被緩存的資產(chǎn)。該特定的應(yīng)用程序版本已損壞,并且無(wú)法在不重新加載頁(yè)面的情況下修復(fù)客戶端的狀態(tài)。在這種情況下,Service Worker 會(huì)通過(guò)發(fā)送 ?UnrecoverableStateEvent
?事件來(lái)通知客戶端??梢杂嗛?nbsp;?SwUpdate#unrecoverable
? 以得到通知并處理這些錯(cuò)誤。
@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號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: