rmc*_*rry 5 javascript settimeout rxjs angular
我有一个对象列表。用户可以单击其中一个,然后加载一个子组件来编辑该组件。
我遇到的问题是,当用户返回列表组件时,子组件必须在 ngOnDestroy 方法中进行一些清理 - 这需要调用服务器来对对象进行最终的“修补”。有时此处理可能会有点慢。
当然,发生的情况是用户返回列表,并且该 api 调用在数据库事务完成之前完成ngOnDestroy,因此用户看到的是过时的数据。
ngOnDestroy(){
this.destroy$.next();
this.template.template_items.forEach((item, index) => {
// mark uncompleted items for deletion
if (!item.is_completed) {
this.template.template_items[index]['_destroy'] = true;
};
});
// NOTE
// We don't care about result, this is a 'silent' save to remove empty items,
// but also to ensure the final sorted order is saved to the server
this._templateService.patchTemplate(this.template).subscribe();
this._templateService.selectedTemplate = null;
}
Run Code Online (Sandbox Code Playgroud)
我知道不建议进行同步调用,因为它会阻塞 UI/整个浏览器,这不太好。
我确信有多种方法可以解决这个问题,但真的不知道哪种方法最好(特别是因为 Angular 不支持同步请求,所以我必须回退到标准 ajax 来做到这一点)。
我确实想到的一个想法是 ngOnDestroy 可以将“标记”传递给 API,然后它可以将该对象标记为“正在处理”。当列表组件执行调用时,它可以检查每个对象以查看它是否具有该标记,并为处于该状态的任何对象显示“刷新陈旧数据”按钮(无论如何,99% 的时间都只是单个项目,用户编辑的最新一篇)。与仅将异步调用更改为同步调用相比,这似乎是一种糟糕的解决方法,并且需要大量额外的代码。
其他人一定也遇到过类似的问题,但除了这个同步问题之外,我似乎找不到任何明确的例子。
编辑
请注意,该子组件上已经有一个 CanDeactive 防护。它要求用户确认(即放弃更改)。因此,如果他们点击确认,那么 ngOnDestroy 中的清理代码就会被执行。但请注意,这不是典型的角度形式,用户真正“放弃”更改。本质上,在离开此页面之前,服务器必须对最终数据集进行一些处理。因此,理想情况下,我不希望用户在 ngOnDestroy 完成之前离开 - 如何强制它等待 api 调用完成?
我的 CanDeactive 防护的实现方式与 Hero 应用程序的官方文档几乎相同,它连接到通用对话服务,提示用户是否希望留在页面上或继续离开。这里是:
canDeactivate(): Observable<boolean> | boolean {
console.log('deactivating');
if (this.template.template_items.filter((obj) => { return !obj.is_completed}).length < 2)
return true;
// Otherwise ask the user with the dialog service and return its
// observable which resolves to true or false when the user decides
return this._dialogService.confirm('You have some empty items. Is it OK if I delete them?');
}
Run Code Online (Sandbox Code Playgroud)
不过,文档并没有明确说明我的情况 - 即使我将清理代码从 ngOnDestroy 移至对话框的“YES”方法处理程序,它仍然必须调用 api,因此 YES 处理程序仍会在 API 之前完成做了,我又遇到了同样的问题。
更新
阅读所有评论后,我猜测解决方案是这样的。将守卫从:
return this._dialogService.confirm('You have some empty items.
Is it OK if I delete them?');
Run Code Online (Sandbox Code Playgroud)
到
return this._dialogService.confirm('You have some empty items.
Is it OK if I delete them?').subscribe(result => {
...if yes then call my api and return true...
...if no return false...
});
Run Code Online (Sandbox Code Playgroud)
正如您所说,有很多方法,它们取决于您的整个应用程序、数据流和用户体验流的设置方式的其他细节,但感觉您可能想看看CanDeactivate防护方法,以确保用户无法离开路线,直到您Observable<boolean>|Promise<boolean>决心true。
因此,这是一种异步等待的方式,直到您的服务确认服务器上的内容发生更改。
[更新]
这取决于您的用户确认实施,但沿着这些思路......
waitForServiceToConfirmWhatever(): Observable<boolean> {
return yourService.call(); //this should return Observable<boolean> with true emitted when your server work is done
}
canDeactivate(): Observable<boolean> {
if(confirm('do you want to leave?') == true)
return this.waitForServiceToConfirmWhatever();
else
Observable.of(false)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6656 次 |
| 最近记录: |