在Angular 4中的服务中使用Router [英] Using Router in services in Angular 4

查看:99
本文介绍了在Angular 4中的服务中使用Router的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用Angular 2/4大约一年了,我继续回到这个难题,是否将Router投入服务是否被视为一种不好的做法?

这是更具架构性的问题.我相信尚无确切答案,但我想听听您的意见.所以这是两个例子.

  1. 考虑下一个代码.假设我们有一些组件,我们想在执行某些操作(例如,执行以下操作)后将用户重定向到特定的路由用户添加了一个新实体,我们希望将其重定向回网格.

component.ts

constructor(private router: Router) {}

someAction() {
  // Some code here
  this.router.navigate(['/grid']);
}

在这里,我认为使用Router很好,因为Router和Component都是UI层.

  1. 现在让我们假设我们有auth.service.ts,它负责身份验证.我们希望能够从应用程序中注销用户,并且我们具有logout()功能.

auth.service.ts

constructor(private router: Router) {}

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

因此要进行结构性思考:

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

例如,我当时正在考虑将eventEmitter放在authService上并在 app.component.ts 中进行订阅,但仍不确定是否比将它包含在服务中更好./p>

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

编辑

另一个示例:UI是带有任务的日历.

有一个服务可以处理所有数据流并为日历提供数据.日历本身并不要求提供数据,而是从服务中订阅数据更改.

现在,我需要将用户引导至与此日历不同的屏幕.想象一下用户在下周/月/年的点击情况.

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

它们被封装在服务内部.那么在这种情况下,您会使用路由器吗?

解决方案

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);
      }
    );
  }
}

在您的app.module中提供它,或者我为所有单例创建了core.module来保持我的app.module清洁

{
  provide: HTTP_INTERCEPTORS,
  useClass: ErrorInterceptor,
  multi: true
}

使用类似这样的东西,您不必在服务中添加路由,当令牌无效时,您会从api中获得401.

您可能需要弄清楚这段代码,尝试尽可能通用.

I've been using Angular 2/4 for about a year now and I keep returning to this dilemma whether injecting Router into service can be considered as a bad practice?

This is more architectural question. I believe there's no exact answer for it, but I want to hear your opinion. So here are 2 examples.

  1. Consider the next code. Imagine we have some component and we want to redirect user to specific route after some action, e.g. user added a new entity and we want to redirect him back to the grid.

component.ts

constructor(private router: Router) {}

someAction() {
  // Some code here
  this.router.navigate(['/grid']);
}

Here I think it's perfectly fine to use Router, because both Router and Component is UI layer.

  1. Now let's imagine we have auth.service.ts and it's responsible for authentication. We want to be able to logout user out of the application and we have logout() function to do that.

auth.service.ts

constructor(private router: Router) {}

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

So thinking architecturally:

  1. What do you think of such router usage inside the service?
  2. Do you think it's a valid approach?
  3. If not what do you suggest in this case?

I was thinking about putting eventEmitter on authService and subscribe to it inside app.component.ts for instance, but still not sure if it's better than having it in the service.

I appreciate any comments for this case. Thanks a lot!

EDIT

Another example: UI is a calendar with tasks.

There's a service that handles all data-flow and provides data for the calendar. Calendar itself doesn't ask for the data, instead it subscribes to the data change from the service.

Now I need to route user to a different screen from this calendar. Imagine user clicks next week/month/year.

This data stored in the route URL so user can stay on the same day after page refresh, but calendar component doesn't know about the days/weeks/months.

They are incapsulated inside the service. So will you use router in service in this case?

解决方案

TL;DR: Its always better to do it from the component, since you can see where are the moving parts, wether in a service it can be done, but it is hard to identify as you will always check first the component.


You can use Guards for that purpose and interceptors, i've added an error interceptor like the following, to route to logout when i get a 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);
      }
    );
  }
}

Provide it in your app.module or in my case i've created a core.module for all the singletons to keep clean my app.module

{
  provide: HTTP_INTERCEPTORS,
  useClass: ErrorInterceptor,
  multi: true
}

With something like this you don't have to put routing in a service, you will get a 401 from your api when token is invalid.

You might have to work out a bit this code, tried to be as generic as possible.

这篇关于在Angular 4中的服务中使用Router的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆