Angular documentation提供了以下示例来激活软件更新:
constructor(updates: SwUpdate) {
updates.available.subscribe(event => {
if (promptUser(event)) {
updates.activateUpdate().then(() => document.location.reload());
}
});
}
根据我的观察,调用本身不足以激活新版本,需要重新加载。但是,即使没有document.location.reload()
调用,activateUpdate()
也足够。
activateUpdate()
呼叫的目的是什么?重新加载就足够了,为什么还要调用它呢?
答案 0 :(得分:2)
Angular ServiceWorker的幕后工作背景:
此行为与ServiceWorkers通常的工作方式略有不同。它旨在允许向新客户端提供最新版本,但又不破坏现有客户端(通过向他们提供新内容,而这些新内容并非旨在与他们已经在使用的旧HTML / CSS / JS代码一起使用)。
现在,回到activeUpdate()
:
这基本上告诉SW将客户端设置为最新版本。操作完成后,来自客户端的新请求将得到最新的应用程序版本。这是不安全的,因此建议重新加载页面以确保所有代码都来自新版本。
重新加载就足够了吗?
这基本上取决于浏览器如何在重新加载时分配Client.id
。如果浏览器在重新加载时为标签分配了新的ID,则SW仍将提供最新版本,因此swUpdate.activeUpdate()
是不必要的。另一方面,如果浏览器保留相同的客户端ID,则SW将提供不带swUpdate.activeUpdate()
的旧版本。
当前,Chrome似乎分配了一个新ID(因此,activeUpdate()
在重新加载之前是不必要的)。我在the SW spec中找不到结论性的内容,因此我不确定这是否符合规范以及所有浏览器是否都执行相同操作。
(过去,浏览器过去的行为可能也不同,因此activeUpdate()
是必需的,但是此后规范/浏览器已进行了更新,如果您打算重新加载,则会变得多余。)
因此,如果您确认支持的浏览器在这方面的行为符合预期,则无需在重新加载之前调用activeUpdate()
。
请注意,文档示例只是可用API的简化图示。在真实的应用程序中,有几种处理更新的方法(取决于应用程序的要求)。
例如,您可以:
同样,并非所有策略都适用于所有类型的应用,因此请选择最适合您的一种。
编辑:
顺便说一句,如果您对如何改进文档有任何建议,请提出一个问题(或者最好还是提出提起请求)!
答案 1 :(得分:0)
从github代码中,我了解的是,activateUpdate()
将对服务工作者线程执行postMessage(),以使其了解新数据和状态,并在解决诺言之后(服务工作者)线程知道这一点),然后重新加载页面。
https://github.com/angular/angular/blob/7.2.11/packages/service-worker/src/update.ts#L57-L64
activateUpdate(): Promise<void> {
if (!this.sw.isEnabled) {
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
}
const statusNonce = this.sw.generateNonce();
return this.sw.postMessageWithStatus('ACTIVATE_UPDATE', {statusNonce}, statusNonce);
}
https://github.com/angular/angular/blob/master/packages/service-worker/src/low_level.ts#LC105
postMessageWithStatus(type: string, payload: Object, nonce: number): Promise<void> {
const waitForStatus = this.waitForStatus(nonce);
const postMessage = this.postMessage(type, payload);
return Promise.all([waitForStatus, postMessage]).then(() => undefined);
}