Javascript 角度4-如何确保在航行离开前完成Ngondestry
我有一个物品清单。用户可以单击其中一个,然后加载子组件以编辑该组件 我遇到的问题是,当用户返回列表组件时,子组件必须在Ngondestory方法中进行一些清理,这需要调用服务器对对象进行最后的“修补”。有时这种处理可能有点慢 当然,发生的情况是用户返回列表,并且在Javascript 角度4-如何确保在航行离开前完成Ngondestry,javascript,angular,rxjs,settimeout,Javascript,Angular,Rxjs,Settimeout,我有一个物品清单。用户可以单击其中一个,然后加载子组件以编辑该组件 我遇到的问题是,当用户返回列表组件时,子组件必须在Ngondestory方法中进行一些清理,这需要调用服务器对对象进行最后的“修补”。有时这种处理可能有点慢 当然,发生的情况是用户返回列表,并且在ngondestory中的数据库事务完成之前,api调用就完成了,因此用户会看到过时的数据 ngOnDestroy(){ this.destroy$.next(); this.template.template_it
ngondestory
中的数据库事务完成之前,api调用就完成了,因此用户会看到过时的数据
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;
}
我知道不建议进行同步调用,因为它会阻塞UI/整个浏览器,这并不好
我确信有多种方法可以解决这个问题,但我真的不知道哪种方法是最好的(特别是因为Angular不支持同步请求,所以我不得不回到标准ajax来实现这一点)
我确实想到的一个想法是,Ngondestory可以向API传递一个“标记”,然后它可以将该对象标记为“正在处理”。当列表组件进行调用时,它可以检查每个对象是否有该标记,并为处于该状态的任何对象显示一个“刷新过时数据”按钮(99%的时间都是单个项目,是用户编辑的最新项目)。这似乎是一个有点垃圾的解决方法,与将异步调用更改为同步调用相比,需要大量额外的代码
其他人肯定也遇到过类似的问题,但我似乎找不到任何明确的例子,除了
编辑
请注意,此子组件上已经有一个CanDeactive保护。它要求用户确认(即放弃更改)。因此,如果他们单击确认,则会执行Ngondestory中的清理代码。但请注意,这不是一个典型的角度形式,用户实际上是“放弃”更改。基本上,在离开此页面之前,服务器必须对最后一组数据进行一些处理。因此,理想情况下,我不希望用户在Ngondestory完成之前离开—我如何强制它等待api调用完成
我的CanDeactive guard的实现与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?');
}
到
正如您所说,有很多方法,它们取决于您的整个应用程序、数据流和用户体验流的其他细节设置,但您可能想看看
CanDeactivate
guard方法,该方法确保用户在您的Observable | Promise
解析为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)
}
WaitForService配置文件():可观察{
return yourService.call();//当服务器工作完成时,它应该返回Observable并发出true
}
canDeactivate():可观察{
if(confirm('您想离开吗?')==true)
返回此.waitForServiceToConfigWhather();
其他的
可观察的(假)
}
我能想到的一个“解决办法”是将您的列表放在客户端。您可以将列表作为JS数组或对象,并基于此显示UI。在详细信息屏幕中编辑后,在更新其他相关数据时,在服务调用的ngondestory
上清除项目上有一个过时的标志。查看CanDeactivate或guards,请参阅示例。谢谢,这不是解决方案。我将更新问题以解释原因。@rmcsharry这是一个解决方案。您在CanDeactivate
中的用户确认不是解决方案。如果这是解决方案,为什么不起作用?我已经有了一个CanDeactivate守卫。当防护装置激活时,会提示用户。当他们“继续”走的时候,Ngondestory被叫来做清理工作。谢谢,但是路线已经有了一个坦率的守卫。它会提示用户是/否,如果用户回答是,则会触发正在进行清理的Ngondestory代码。在那之前我不能做清理工作。因此出现了一个catch-22。我要做的是像组件中的常规单击处理程序一样有yes/no提示。然后,如果用户单击“是”,我将转到路由器。导航['whereverYourListIs']。然后,使用我在回答中描述的CanDeactivate
。我看不出您有什么理由在CanDeactivate
guard中处理yes/no。这属于组件本身,即使是在组件ngondestory
中也不属于组件本身,因为它只是一个常规的用户操作,就像其他任何与组件生命周期无关的操作一样,用户简单的“否”不应该做任何事情。希望这是有意义的。我不处理是/否。用户可以导航到任何地方,但我不知道(或关心)他们下一步想去哪里。无论他们选择去哪里,阳光都会燃烧。它检测是否还有工作要做(即,对象未处于“最终”状态),警卫抛出提示(基本上,你确定要离开并扔掉其他东西吗?)。单击“否”不会执行任何操作,正如CanDeactive的本意一样-用户将停留在页面上。如果他们单击“是”,警卫将允许他们继续,卸载组件并自动调用Ngondestory。我认为答案可能在于您的陈述“用户不能离开路由,直到您的可观察承诺被解析为真”——那么我如何更改警卫以确保在离开之前解决对API的调用?例如,我可以将api调用链接到dialog服务调用吗?好的,在用户单击“是”之后,有什么阻止您向您的服务发出额外的请求,并等待其可观察的解析为true
,然后允许用户离开(CanDeactivate
返回true
),这是一个错误
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...
});
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)
}