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

时间:2019-11-17 17:26:46

标签: angular synchronous angular-httpclient

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

根据此similar question'window:unload'是仅同步事件,因此我不能在主机侦听器的主体中使用异步API调用。

但是,使用XMLHttpRequest()的公认解决方案是being deprecated according to Mozilla.

  

注意:从Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 /   SeaMonkey 2.27),Blink 39.0和Edge 13上的同步请求   主线程由于对线程的负面影响而被弃用   用户体验。

我需要一个更可靠的解决方案。有没有一种方法可以在Angular中发送SYNCHRON 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
    );

  }

更新

我正在研究,可能已经找到了possible solution with sendBeacon()。我不确定如何在Angular中实现此功能,或者是否建议这样做。有什么建议吗?

  

为解决此问题,分析和诊断代码具有   历史上在卸载时进行了同步XMLHttpRequest调用,或者   beforeunload事件处理程序提交数据。同步   XMLHttpRequest阻止了文档的卸载过程,   转弯会导致下一个导航速度变慢。

     

这是sendBeacon()出现的地方。通过使用sendBeacon()方法,   用户将数据异步传输到Web服务器   代理商有机会这样做,而不会延迟卸载或   影响下一个导航的性能。这解决了所有   提交分析数据的问题:数据已发送   可靠地,它是异步发送的,并且不会影响加载   的下一页。

1 个答案:

答案 0 :(得分:1)

我能够用navigator.sendBeacon()

解决此问题
  

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

第二种可能的解决方法是将keepalive设置为true的send the request via the 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}`);
  }