3

I am trying to capture browser events like tab-close and refresh in my angular 6 Application. It's working fine in debug mode but its not working if I close debug mode and run the application. below is the piece of code

registerDOMEvents() {
  window.addEventListener('unload', () => {
    if (this.validNavigation === 0) {
      this.endSession();
    }
  });
  document.addEventListener('keydown', (e) => {
    const key = e.which || e.keyCode;
    if (key === 116) {
      this.validNavigation = 1;
    }
  });
}
endSession() {
  this.logout();
  localStorage.clear();
}
ngOnInit() {
  this.registerDOMEvents();
}

What might me the problem for this issue?

Vamshi
  • 9,194
  • 4
  • 38
  • 54
Pavan
  • 153
  • 3
  • 13
  • have you use @HostLisener instead of directly using addEventListener – Nithya Rajan Feb 28 '19 at 05:45
  • Yeah at first I used @HostListner only.. but I was facing same issue in that also. – Pavan Feb 28 '19 at 05:48
  • @BearNithi I think before calling the event , the tab close is happening..so that without debug mode its not working.. Do I need to change any configuration or something ? – Pavan Feb 28 '19 at 06:22

2 Answers2

3

You need to use beforeunload instead of unload. beforeunload is more reliable and triggers when the document and its resources are about to be unloaded whereas unload fires when page is already unloading.

Your endSession() must be synchronous, since browser will not wait when any callbacks will be called. As I know angular http service doesn't provide synchronous http calls, but you can do it by yourself with XMLHttpRequest:

window.addEventListener("beforeunload", function (event) {
  var client = new XMLHttpRequest();
  client.open("POST", "http://url/to/endsession", false); // third parameter indicates sync xhr
  client.setRequestHeader("Content-Type", "application/json");
  client.send('{userId: "42"}');
  console.log('done!!!'); // outputs when a response is received 
});

Also take a look this article. Probably you can use navigator.sendBeacon if a browser of your clients supports that feature.

AlbertK
  • 11,841
  • 5
  • 40
  • 36
  • That's superb answer. – Nithya Rajan Feb 28 '19 at 07:39
  • @AlbertK Yeah.. the thing is beforeunload is triggering for both refresh and tab close .. is there any way to differentiate it ? – Pavan Feb 28 '19 at 12:51
  • Browsers don't provide such API, so it is a big challenge. You need to handle `keydown` event like you do, hyperlinks click event, `Refresh` button click (as I know it is impossible) and etc. – AlbertK Feb 28 '19 at 14:40
  • @AlbertK Even though I am using beforeunload, facing same problem its working in debug mode but without debug mode its not working.. – Pavan Mar 04 '19 at 06:20
  • @AlbertK I need to make an API call to back-end as soon as user closes browser tab.. Here the problem is its not waiting for back-end response.. so that without debug mode its not making API call only – Pavan Mar 04 '19 at 06:25
  • how do you make the request? is it synchronous? – AlbertK Mar 04 '19 at 07:13
  • @AlbertK Yeah I have tried using async/await also..but didn't help – Pavan Mar 04 '19 at 09:56
  • you should use only synchronous. Async/await is asynchronous and it definitely will not work. – AlbertK Mar 04 '19 at 10:12
  • @AlbertK Okiee.. If u have any example plz provide me the link.. It would help me to solve the problem.. – Pavan Mar 04 '19 at 11:03
0
@HostListener('window:unload')
async ngOnDestroy() {

  await this.oneService.handleSignOut();

}

This will only hit at the time of close window/Tab.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83