我们有一个为我们编写的 Angular 应用程序,我们正试图找出一个特定的问题(请参阅下面我的长篇论文)。基本上,它是一个系统,其中一些数字输入应该控制背光和显示的页面。如果数字输入打开,背光也应该打开,应用程序应该正常工作,允许用户交互。
然而,如果没有那个数字输入信号,应用程序应该给出一个空白页并关闭背光,以便用户看不到任何东西 和 无法以某种盲目的方式与真实页面交互。
背光由后端进程控制,该进程还使用 Angular 路由将信息传送到前端(两者都在同一设备上运行)。但是,网页上显示什么内容的决定完全在前端的控制之下。
我们看到这样一种情况,如果数字输入被快速关闭和打开,我们有时会打开背光但有一个空白页,我想知道在通过路由器传递事件时是否存在某种竞争条件.
在代码方面,我们有一个效果,它监视来自后端(不是直接)的数字输入信号,如下所示:
@Effect({ dispatch: false })
receiveDigitalInputEvent$ = this.actions.pipe(
ofType(AppActionTypes.RECEIVE_DIGITAL_INPUT),
map((action: AppActions.ReceiveDigitalInput) => action.payload),
withLatestFrom(this.store.pipe(select(getRouterState))),
tap(([data, routerState]) => {
const currUrl = routerState ? routerState.state.url : '';
const { isDigitalInputSet, someOtherStuff } = data;
this.forceNavigateIfNeeded(isDigitalInputSet, currUrl);
})
);
forceNavigateIfNeeded(isDigitalInputSet: boolean, currUrl) {
if (isDigitalInputSet && currUrl.endsWith('/blank')) {
this.router.navigateByUrl('/welcome');
else if (! isDigitalInputSet && ! currUrl.endsWith('/blank')) {
this.router.navigateByUrl('/blank');
}
}
这基本上是在数字输入事件到达时:现在,这正常工作,只是快速转换似乎导致了问题。
我对 Angular 内部结构没有太多了解,但我认为传入的事件正在以某种方式排队等待通过路由机制传递(我相信后端通过 Web 套接字将内容推送到前端)。
我查看了 Angular 源代码并注意到
navigateByUrl
使用 promise 来完成它的工作,因此代码可能会在页面实际更改之前返回以获取下一个消息队列项。我只是想要一个有更多 Angular nous 的人来检查我的推理,或者让我知道我的建议是否是垃圾。至于我的建议:navigateByUrl('/blank')
这启动了一个 promise 。 routerState.state.url
从非空白变为空白),我们开始处理 ON 消息。在这个阶段,我们有一个带有(陈旧)非空白页面的 ON 消息,所以 forceNavigateIfNeeded()
什么也没做。 navigateByUrl('/blank')
promise 完成,将页面设置为空白。 现在我们似乎有了最初描述的情况,背光打开的空白页面。
这甚至可以用 Angular/Typescript 实现吗?它似乎依赖于这样一个事实,即传入的消息被排队并尽快采取行动(以单线程方式),而前端导航(更重要的是,您当前页面的更新记录)可能需要一段时间。
有人可以建议这是否可行,如果可行,有什么好的解决方法?
我认为在
forceNavigateIfNeeded()
等待是个坏主意为了完成 promise ,但我不知道还能怎么做。
最佳答案
尽管您的问题非常复杂,但我可以看到一个值得检查的可疑代码。
...
withLatestFrom(this.store.pipe(select(getRouterState))),
...
这可能是导致您出现问题的原因,因为它正在获取最新信息。它不会请求更新,也不会等待更新。我们遇到了类似的问题,毫秒也在起作用,我想出了解决方法,我替换了 withLatestFrom
与 switchMap
运算符(operator)。我不确定它是否适用于您的情况,但您可以尝试一下。map((action: AppActions.ReceiveDigitalInput) => action.payload),
switchMap(data => //data === action.payload
this.store.select(getRouterState).pipe(map(routerState => ({ data, routerState }))
),
tap(({data, routerState}) => { ... }
编辑:在我们的例子中,我们在
switchMap
中使用了一个自定义选择器。 ,它比较当前和以前的状态并返回比较结果。老实说,我不是 100% 确定这是否也对您有帮助,但在我们的案例中这是一个必要的拼图。export const getFeshRouterState= pipe(
select(getRouterState),
startWith(null as RouterStateInterface),
pairwise(),
map(([prev, curr]) => /* do some magic here and return result */),
);
抱歉最初的困惑。
关于javascript - Angular/TS promise 会导致乱序执行吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67412249/