在Angular 4中的服务中使用Router

Vit*_*vzh 11 angular

我已经使用Angular 2/4大约一年了,我一直在回到这个困境,无论是否将路由器注入服务都被认为是一种不好的做法?

这是更具建筑性的问题.我相信没有确切的答案,但我想听听你的意见.所以这里有两个例子.

  1. 考虑下一个代码.想象一下,我们有一些组件,我们希望在一些操作后将用户重定向到特定路由,例如用户添加了一个新实体,我们想将他重定向回网格.

component.ts

constructor(private router: Router) {}

someAction() {
  // Some code here
  this.router.navigate(['/grid']);
}
Run Code Online (Sandbox Code Playgroud)

在这里我认为使用Router非常好,因为路由器和组件都是UI层.

  1. 现在让我们假设我们拥有auth.service.ts它并且它负责身份验证.我们希望能够将用户退出应用程序,我们有logout()能力这样做.

auth.service.ts

constructor(private router: Router) {}

logout() {
  // Cleanup token, storage, etc.
  this.router.navigate(['/login']);
}
Run Code Online (Sandbox Code Playgroud)

所以在架构上思考:

  1. 您如何看待服务中的这种路由器使用情况?
  2. 你认为这是一种有效的方法吗?
  3. 如果不是,你在这种情况下建议什么?

我正在考虑在app.component.ts中eventEmitter加入authService并订阅它,但仍然不确定它是否比在服务中使用它更好.

我感谢对此案的任何评论.非常感谢!

编辑

另一个例子:UI是一个包含任务的日历.

有一种服务可以处理所有数据流并为日历提供数据.日历本身不会询问数据,而是订阅服务中的数据更改.

现在我需要将用户路由到此日历的不同屏幕.想象一下,用户点击下周/月/年.

此数据存储在路径URL中,因此用户可以在页面刷新后的同一天停留,但日历组件不知道日期/周/月.

它们包含在服务中.那么在这种情况下你会使用路由器吗?

Son*_*300 9

TL; DR:总是更好地从组件中做到这一点,因为你可以看到移动部件在哪里,在服务中可以做到,但很难识别,因为你总是先检查组件.


您可以使用Guards用于此目的和拦截器,我添加了一个错误拦截器,如下所示,当我得到401时路由到注销:

import { Injectable } from '@angular/core';
import { HttpEvent, HttpErrorResponse, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
  constructor(private router: Router) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch(
      (err: HttpErrorResponse) => {
        if (this.router.url !== '/login' && err.status === 401) {
          this.router.navigate(['/logout']);
        }
        return Observable.throw(err);
      }
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

在你的app.module中提供它,或者在我的情况下我为所有单身人士创建了一个core.module来保持我的app.module干净

{
  provide: HTTP_INTERCEPTORS,
  useClass: ErrorInterceptor,
  multi: true
}
Run Code Online (Sandbox Code Playgroud)

有了这样的东西,你不必在服务中放置路由,当令牌无效时,你将从api获得401.

您可能需要考虑一下这段代码,尽可能地通用.