使用 Angular 关闭浏览器 window / 选项卡时执行异步服务获取
Perform an asynchronous service get when closing browser window / tab with Angular
我目前正在尝试让 Angular 应用程序在用户试图离开我的页面时发出 API 服务调用。通过关闭选项卡 / window,或输入外部 URL.
我已经尝试实施我在此处看到的关于 Whosebug 问题的几种不同方式,但 none 似乎达到了预期的效果。有些人提到同步 ajax 请求,这些请求已经或正在 Chrome 的 onbeforeunload 中被弃用。其他人建议使用 XMLHttpRequests,这似乎遭遇了同样的命运。
我尝试使用
@HostListener('window:onbeforeunload', ['$event'])
,等同于HTML(window:beforeunload)="doBeforeUnload($event)"
,但一律不予配合。我可以让 console.logs 出现,但 API 从未收到任何注销用户的电话。
我还使用了 navigator.sendBeacon
,尽管它的函数返回 true,表示作业已发送到浏览器队列,但没有任何结果。
目前注销功能是这样的:
userLogout(): Observable<any> {
return this.apiService.get('/Account/Logout/');
}
这又是一个通用的 http get 函数:
get<T>(url: string, options?: { params: HttpParams }): Observable<any> {
return this.httpRequest<T>('get', url, null, options ? options.params : null);
}
完整的 url 是通过使用 HttpInterceptor 添加的。注销功能本身正在运行,因为它在菜单选项中使用,手动使用时可以按预期工作。所以功能应该不是问题。
我想做的就是以同步或异步方式调用 userLogout 函数,并通知后端用户已离开。
经过一些修改,我最终得到了基于此 answer 的解决方案,尽管出于某种原因,它在我的第一次尝试中并不适用。
我向组件添加了以下 HostBinding:
@HostListener('window:beforeunload', ['$event']) beforeunloadHandler(event) {
this.pageClosed();
}
它调用一个简单的函数,该函数将使用身份验证服务注销方法。
pageClosed() {
this.authenticationService.userLogoutSync();
}
我必须创建一个单独的注销函数,这样它才能同步。 Headers 还必须添加后端授权,因为我的 Http 拦截器无法捕获 XMLHttpRequest 并自行添加它们。
const xhr = new XMLHttpRequest();
xhr.open('GET', environment.backend + '/Account/Logout/', false);
xhr.setRequestHeader('Authorization', 'Bearer ' + this.jwtService.getAccessToken());
xhr.send();
}
对于 angular 中的我来说,async/await
在关闭浏览器选项卡/更改选项卡时进行 http 调用效果很好 url。
@HostListener('window:beforeunload', ['$event'])
async beforeunloadHandler(event) {
await triggerSyncLogout();
}
async triggerSyncLogout(){
let url = 'www.sample.com';
let reqHeaders = new HttpHeaders().append('Authorization', token).append('Accept', 'application/json');
const options = {
headers: reqHeaders,
withCredentials: true,
observe: 'response' as 'response'
}
return await this.http.get<any>(url, options).toPromise();
}
我目前正在尝试让 Angular 应用程序在用户试图离开我的页面时发出 API 服务调用。通过关闭选项卡 / window,或输入外部 URL.
我已经尝试实施我在此处看到的关于 Whosebug 问题的几种不同方式,但 none 似乎达到了预期的效果。有些人提到同步 ajax 请求,这些请求已经或正在 Chrome 的 onbeforeunload 中被弃用。其他人建议使用 XMLHttpRequests,这似乎遭遇了同样的命运。
我尝试使用
@HostListener('window:onbeforeunload', ['$event'])
,等同于HTML(window:beforeunload)="doBeforeUnload($event)"
,但一律不予配合。我可以让 console.logs 出现,但 API 从未收到任何注销用户的电话。
我还使用了 navigator.sendBeacon
,尽管它的函数返回 true,表示作业已发送到浏览器队列,但没有任何结果。
目前注销功能是这样的:
userLogout(): Observable<any> {
return this.apiService.get('/Account/Logout/');
}
这又是一个通用的 http get 函数:
get<T>(url: string, options?: { params: HttpParams }): Observable<any> {
return this.httpRequest<T>('get', url, null, options ? options.params : null);
}
完整的 url 是通过使用 HttpInterceptor 添加的。注销功能本身正在运行,因为它在菜单选项中使用,手动使用时可以按预期工作。所以功能应该不是问题。
我想做的就是以同步或异步方式调用 userLogout 函数,并通知后端用户已离开。
经过一些修改,我最终得到了基于此 answer 的解决方案,尽管出于某种原因,它在我的第一次尝试中并不适用。
我向组件添加了以下 HostBinding:
@HostListener('window:beforeunload', ['$event']) beforeunloadHandler(event) {
this.pageClosed();
}
它调用一个简单的函数,该函数将使用身份验证服务注销方法。
pageClosed() {
this.authenticationService.userLogoutSync();
}
我必须创建一个单独的注销函数,这样它才能同步。 Headers 还必须添加后端授权,因为我的 Http 拦截器无法捕获 XMLHttpRequest 并自行添加它们。
const xhr = new XMLHttpRequest();
xhr.open('GET', environment.backend + '/Account/Logout/', false);
xhr.setRequestHeader('Authorization', 'Bearer ' + this.jwtService.getAccessToken());
xhr.send();
}
对于 angular 中的我来说,async/await
在关闭浏览器选项卡/更改选项卡时进行 http 调用效果很好 url。
@HostListener('window:beforeunload', ['$event'])
async beforeunloadHandler(event) {
await triggerSyncLogout();
}
async triggerSyncLogout(){
let url = 'www.sample.com';
let reqHeaders = new HttpHeaders().append('Authorization', token).append('Accept', 'application/json');
const options = {
headers: reqHeaders,
withCredentials: true,
observe: 'response' as 'response'
}
return await this.http.get<any>(url, options).toPromise();
}