【问题标题】:Angular Router is slowAngular路由器很慢
【发布时间】:2020-06-08 00:21:40
【问题描述】:

我在后台使用 Ionic 和 Angular。

设置

"@angular/router": "~9.1.9",
"@ionic/angular": "^5.1.1",
"rxjs": "^6.5.5",

我使用以下登录方法:触发时显示微调器,加载数据,路由到另一个页面,然后再次隐藏微调器。

loginWithGoogle() {
    this.showSpinner = true;
    this.authService.getAuthSessionPersistence()
        .pipe(
            concatMap(() => this.authService.getAuth().signInWithPopup(new auth.GoogleAuthProvider())),
            concatMap(() => this.databaseService.getUserModel()
                .pipe(
                    concatMap(userModel => {
                        if (Object.keys(new UserInit()).every(key => userModel[key])) {
                            return of(userModel).pipe(first());
                        }

                        return this.authService.getUser()
                            .pipe(
                                concatMap(user => this.databaseService.createUser(user.uid, userModel))
                            );
                    }),
                    concatMap(userModel => this.store.dispatch([
                            new SaveUserAction(userModel),
                            new LoadFixturesAction(),
                            new LoadTeamsAction(),
                            new LoadTransactionsAction(),
                        ])
                    ),
                    tap(() => this.router.navigateByUrl('tabs/home'))
                )),
            finalize(() => this.showSpinner = false)
        )
        .subscribe();
}

问题是微调器在路由发生之前就被隐藏了。用户会再次看到不太友好的登录屏幕。

正如您在上面的代码中看到的:最后一个 RxJS 运算符是使用 finalize,这是微调器被隐藏的地方。

你知道为什么路由器导航需要很长时间吗?

【问题讨论】:

  • 那么如果将“finalize”移动到“tap”之后的位置会发生什么?
  • @SergeyRudenko 效果一样

标签: angular rxjs angular-routing


【解决方案1】:

我自己对 rxjs 操作符不太熟悉,但是你有的 router.navigateByUrl 方法根据:https://angular.io/api/router/Router#navigateByUrl返回一个promise

这意味着您的代码可以在解决此类承诺后隐藏微调器:

...

tap(() => this.router.navigateByUrl('tabs/home').then(()=>{
        this.showSpinner = false
    }) 
)

...

【讨论】:

  • 你的想法是对的。 Tap 会产生副作用,并且不会等待 promise 解决。将 Promise 转换为 observable 和 concatinating 解决了这个问题。 concatMap(() => from(this.router.navigateByUrl('tabs/home')))
【解决方案2】:

我认为你可以在 finalize() 之前通过 NavigationEnd 事件将 concatMap 加入到另一个 Observable 链中。

...
concatMap(() => this.router.events.pipe(
  filter(event => event instanceof NavigationEnd),
)),
finalize(() => this.showSpinner = false),

这样,只有在下一个 NavigationEnd 事件之后,链才会被释放(并触发 finalize)。

【讨论】:

  • 您使用 concatMap 和 observable 的方法是正确的。其实我更喜欢这里的解决方案: concatMap(() => from(this.router.navigateByUrl('tabs/home')))
【解决方案3】:

感谢我们设法找到解决方案的答案。

错误

tap(() => this.router.navigateByUrl('tabs/home'))
  • this.router.navigateByUrl('tabs/home') 返回一个承诺
  • 点击会产生副作用,并且不会等待承诺解决

解决方案

concatMap(() => from(this.router.navigateByUrl('tabs/home')))
  • from() 将 promise 转换为 observable
  • concatMap() 等待 observable

【讨论】:

    猜你喜欢
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多