angular - NGXS如何在异步调用后触发Angular重新渲染?
问题描述
我正在从我的商店进行一些 api 调用,并且我有一个捕获错误,当抛出错误时触发带有错误消息的模式。问题是,当发生这种情况时,会调用触发模式的方法,但在我单击页面上的某个位置之前不会呈现 html。这只发生在商店内,我已经在应用程序的几个部分进行了模拟,如下所示:
timer(5000)
.pipe(
mergeMap(() => {
throw new Error('Some error');
}),
)
.pipe(
catchError((error) => {
return this.handleError(_(`Couldn't do the thing`))(error);
}),
)
.subscribe((result) => {
console.log(result);
});
我以为我可以注入ChangeDetectorRef
来触发 html 的手动重新渲染,但我得到了NullInjectorError: No provider for ChangeDetectorRef!
,但我无法让它工作。我的问题是:
是否可以在商店中注入,ChangeDetectorRef
它会解决我的问题吗?另外,作为后续问题,是否有其他方法可以规避此问题?根据我一直在阅读的一些事情,这似乎是由于商店在 Angular 范围之外而发生的,所以它不知道需要重新渲染某些东西。
任何帮助将非常感激。
更新:这是一个堆栈闪电战,通过调度一个操作来显示错误消息来说明问题和可能的解决方案。
解决方案
通常更改检测由 zone.js 自动触发,更具体地说,是在 NgZone 中注册的每个(微)任务之后。
默认情况下,NGXS 不在 NgZone 中运行操作处理程序。这是一种有用的性能优化,在大多数情况下您不会注意到差异。特别是当动作处理程序只修改实际状态并且没有副作用时更是如此。但是在您的情况下,动作处理程序有副作用:this.handleError(_("Couldn't do the thing"))(error)
,或confimationService.triggerConfirmation()
在 StackBlitz 中。这种副作用甚至反映在视图中。
现在,仍然有很多方法可以解决这个问题。您所需要的只是在副作用之后触发的单个更改检测周期。这就是它真正有趣的地方:虽然动作处理程序本身并不在 NgZone 中运行,但在 NgZone 中运行着很多周围的代码。这可能确实会触发上述变更检测周期。尤其:
- 如果您的操作是同步的,并且调度它的代码在 NgZone 中运行,那么在当前(微)任务结束时触发的更改检测循环将在副作用之后运行。
- 如果您订阅
Observable
返回的 fromstore.dispatch
,那么该订阅将在 NgZone 内发出并完成。因此,这会在副作用之后触发两个变化检测周期。
(顺便说一句,后者是调度两个嵌套动作在您的 Stackblitz 中起作用的原因:您在那里订阅调度方法!)
如果您想自己调查事件的顺序,请查看此 Stackblitz。控制台输出应该非常准确地告诉您每个场景中发生了什么。
最后,让我们谈谈如何确保正确触发变更检测。实际上有几个选项可供选择:
- 虽然您不能
ChangeDetectorRef
在状态中注入 a,但可以注入ApplicationRef
. 调用其tick
方法将在当前(微)任务结束时异步触发更改检测周期。 - 如果你想利用 zone.js,你也可以注入
NgZone
并使用它的run
方法在 NgZone 中运行你的整个副作用。这具有额外的优势,即由副作用注册的(微)任务也将跟随变化检测周期。 - 如果你想在 NgZone 中运行你的所有代码,你可以
executionStrategy: NoopNgxsExecutionStrategy
在你的NgxsConfig
. 这将覆盖 NGXS 的默认行为并全局导致所有操作处理程序在 NgZone 中运行。
推荐阅读
- java - Spring Security - 公共页面重定向到使用无效会话 ID 登录
- continuous-integration - Gitlab CI 作业在每次部署后运行以报告状态
- postgresql - 为什么在postgres中两个小数位数相等的数值被认为是相等的?
- python - 如何正确导入 SVG 路径到 manim
- php - 使用 PHP 进行 A/B 拆分测试
- ios - UIAlertAction actionsheet 获取数据到 childVC
- java - FusedLocationApi 的问题,已弃用
- javascript - Binance WSS api url is being treated as HTTPS on both Google Chrome and Firefox
- pdf - Error: "There was an error opening this document. The file is damaged and could not be repaired"
- python-3.x - Persian text can not be parsed correctly when crawling a persian website