Angular 8 HostListener 'window:unload'如何在卸载前进行 API 调用



我使用HostListener来检测用户何时重新加载或关闭浏览器窗口。目的是#1检查当前用户是否拥有记录上的"正在编辑"锁,#2如果是,则调用observable来更新数据库。(注意:我已经使用CanDeactivate实现了导航离开组件的锁定系统。HostListener的使用是专门用于重新加载或关闭浏览器窗口(。

根据这个类似的问题,'window:unload'是一个仅同步的事件,因此我不能在主机侦听器的主体中使用异步API调用。

然而,根据Mozilla的说法,使用XMLHttpRequest()的公认解决方案正在被弃用。

注意:从Gecko 30.0开始(Firefox 30.0/Thunderbird 30.0/SeaMonkey 2.27(、Blink 39.0和Edge 13由于主线程对用户体验。

我需要一个更可靠的解决方案。有没有一种方法可以在Angular中发送SYNCHRONOUS api调用来绕过这个限制?或者是否有其他方法可以确保在重新加载或关闭浏览器之前完成API调用?

// @HostListener allows guard against browser refresh, close, etc.
@HostListener('window:unload', ['$event'])
beforeUnloadHander($event) {
// Check if Is Being Edited must be removed
if (this.mustReleaseIsBeingEdited()) {
this.updateIsBeingEditedSub = this.updateIsBeingEdited$(true).subscribe(result => {
return true;
}, err => { console.error(err); }, () => { });
} else {
return true;
}
}

private updateIsBeingEdited$(isBeingEdited): Observable<boolean> {
const editedObj = {
_id: this.record._id,
IsBeingEdited: isBeingEdited,
EditedBy: this.accessLevelService.getUserId()
}
return this.httpService!.postData(
`records/_id/${editedObj._id}/IsBeingEdited/`,
editedObj
);
}

更新

我正在研究,可能已经找到了sendBeacon((的可能解决方案。我不知道如何在Angular中实现这一点,或者这是否是一种推荐的做法。有什么建议吗?

为了解决这个问题,分析和诊断代码历史上在卸载或beforeunload事件处理程序以提交数据。同步XMLHttpRequest阻止卸载文档的过程转弯会使下一个导航看起来更慢。

这就是sendBeacon((的作用所在,当用户代理有机会这样做,而不会延迟卸载或影响下一次导航的性能。这解决了所有分析数据提交的问题:数据被发送可靠地,它是异步发送的,并且不会影响加载下一页的。

我用navigator.sendBeacon((解决了这个问题

使用sendBeacon((方法,数据将被传输当用户代理具有这样做的机会,而不会延迟卸载或影响下一次导航的性能。

第二种可能的解决方案是通过将keepalive设置为true的fetch API发送请求。

这是我用sendBeacon((测试的解决方案。

@HostListener('window:beforeunload', ['$event'])
onBeforeUnload(): void {
/**
* Post a single object to the server
* Send Beacon API to keep request after browser windowunload event
*/
navigator.sendBeacon(`${this.env.apiUrl}/id/${this.id}`);
}

最新更新