在一般的web应用里,经常会需要在每次发送Http请求的时候,添加header或者一些默认的参数。本文就来看看这个需求的几种实现方式。通过这个实现,我们也能够理解Angular的服务,及其providers的原理。
我们的目的是对于每个Http请求,都往Header里面添加一个token,用于在服务器端进行身份验证。因为Http是一个服务,所以我就想当然的想到,我可以通过扩展框架提供的Http
来添加。那么要怎么扩展一个框架提供的服务呢?那就是用providers。
在NgModule
里,有一个属性providers
,一般我们是用它来告诉框架,我们的app要用到我们定义的某些服务,例如我写了一个UserService
用来进行用户数据的读写操作,又比如写一个AuthGuardService
来实现路由的Guard
。对于框架或者使用的其他组件库的服务,我们不需要在这里添加,只需要在imports
里面加入相应的模块即可。
自定义系统服务
那么,如果我们想修改框架提供的某个服务,例如想扩展它,该怎么实现呢?我们可以将扩展的这个服务,添加到providers
里,只是添加的方式不太一样。需要使用下面的方式:
@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, RouterModule, HttpModule ], providers: [UserService, AuthGuardService, { provide: Http, useClass: BaseHttp } ], bootstrap: [ AppComponent ]})
我们扩展了Http
服务,新的服务的类名是BaseHttp
,然后在providers
里使用{ provide: Http, useClass: BaseHttp }
,告诉框架,我们要使用BaseHttp
这个类,来提供对Http
的实现。然后,在Angular的容器里面的Http服务实际上是BaseHttp
这个类的实现,当我们通过注入获得一个Http
实例的时候,也是获得的BaseHttp
的实例。
实现自动添加Header
接下来,我们就来看看怎么实现自动的Header的添加。首先,我想到的第一种方式,就是扩展Http,在它的构造函数里设置一个默认的Header。
在构造函数中实现
@Injectable()export class BaseHttp extends Http { constructor (backend: XHRBackend, options: RequestOptions) { super(backend, options); let token = localStorage.getItem(AppConstants.tokenName); options.headers.set(AppConstants.authHeaderName, token); }}
这个就是在构造函数里面,从localStorage里拿到token,然后放到RequestOptions里。看着似乎没有问题,但是运行的时候发现,这个Http服务是在app初始化的时候创建的,所以这个构造函数在调用的时候,localStorage里可能还没有token。这样,即使用户之后登陆了,之前的默认的options也不会更新。
新闻热点
疑难解答
图片精选