了解 Angular 中的异步订阅

Understanding asynchronicity Subscriptions in Angular

提问人:Issac Howard 提问时间:10/30/2023 更新时间:11/3/2023 访问量:45

问:

我觉得我的问题与异步编程有关,因为当我想要它时没有运行。我通常将我的问题分为用户的角度和开发人员的视角。subscription

用户视角:

当用户位于主页上并单击“主页”导航按钮时,网站将刷新。用户不觉得这有吸引力,并希望它,因为如果用户在主页上并点击主页,那么什么都不会发生。导航图片如下。如果用户在主页之外,那么(显然)如果他们单击主页,那么他们应该被重定向到主页。enter image description here

开发者观点:

在模板初始化期间,代码将检查路由器 URL 是否为 。如果是,则 href 应等于 ,如果不是,则 href 应等于 。下面提供了注释代码。/en/home/en/home#/en/home

杂项服务:

// service that does miscellaneous things, one of which is just detecting a url change
@Injectable({
    providedIn: 'root'
})
export class MiscellaneousService {
    urlChange = new Subject<string>()

    // other properties & methods
}

标头 TS 组件:

export class HomeHeaderComponent implements OnInit {
  currentURL: string = ''
  isHomeRoute: boolean = true
  constructor(private misService: MiscellaneousService, private router: Router) {}
 

  ngOnInit(): void {
    /*
      IMPORTANT READ:
        on every page, we will do a 'urlChange.next()' method to ensure the currentURL is updated.
        I would suppose that the urlChange.next(this.router.url) works but what I am sure of is that the
        subscription does not work as currentURL is always an empty string. I would suppose that this has
        to do with the asyncronousity of subscribe and when it runs. If that is the case, how can I fix this so that 
        the component is always updated to the current URL the user is on?
    */
    this.misService.urlChange.next(this.router.url) 
    this.misService.urlChange.subscribe(currentURL => {
      this.currentURL = currentURL
    })
    console.log(this.currentURL)
    if (this.currentURL == '/en/home') {
      this.isHomeRoute = true
    }
    else {
      this.isHomeRoute = false
    }
  }

那么我怎样才能做到,以便我们订阅任何更改?我需要更改什么?router.url

有关更多参考,下面是模板中作为标题的部分

标题模板:

      <a class="nav-link" [href]="isHomeRoute ? '#' : '/en/home'">
           home<span class="sr-only">(current)</span>
      </a>
      <!-- Other code... -->

Angular TypeScript 异步

评论

1赞 Eliseo 10/30/2023
先订阅,后更改。注意:通常,您订阅一个组件,然后在另一个组件中更改(下一个)。通常,在标头组件中您订阅,在另一个组件中您更改。但是,请参阅下面的答案,要“观察”路由器,请使用 router.events

答:

1赞 NoNamer777 10/30/2023 #1

您可以观察并筛选出事件,以捕获所有成功的路由事件。router.eventsNavigationEnd

router.events
    .pipe(
        // Only take successfull navigation events
        filter((routingEvent) => routingEvent instanceof NavigationEnd),
    )
    .subscribe((routingEvent) => {
        // Do anything with the URL at this point
        console.log(routingEvent.url);
    });

评论

0赞 Issac Howard 10/30/2023
非常感谢你的回答,但从何而来?我从未在我的标头组件中声明过它。this.destroy$
0赞 NoNamer777 10/30/2023
我补充说,可能是偶然的。您可以添加一个名为 Rxjs 的 Subject 的组件变量。然后,你可以调用下一个值,并在 Angular 组件的生命周期钩子中完成流。将它与此运算符结合使用,您不必担心订阅不会被取消订阅,从而在组件被销毁时导致应用程序内存泄漏。如果您的处理以其他方式取消订阅,您可以将其排除在外destroy$OnDestroytakeUntil
0赞 Issac Howard 10/30/2023
类型似乎有问题,您知道我该如何解决吗?它似乎是类型,所以它没有给我一个 URL 属性......如果你能告诉我如何解决它,那就太好了,如果你不能,那就不用担心了,你帮了很多忙!routingEventEvent_2
0赞 NoNamer777 10/30/2023
尝试将其强制转换为 NavigationEnd 事件。.您需要像这样强制转换它,因为过滤器操作不会为您强制转换它,而只是返回确实是 .如果看一下声明,它是不同导航事件的类型联合,包括 NavigationEnd 事件类型。您还可以在管道链中包含来自 Rxjs 的映射运算符,如下所示:将其转换为正确的类型。这样,您就不必在订阅中进行强制转换(routingEvent as NavigationEnd).urlEvent_2Event_2map(event => event as NavigationEnd),