问题一:如何援用公有库
起初认为既然node_modules
是用来寄存装置的包的,那么间接把 @yunzhi
放进node_modules
里就能够了。
尝试之后发现,尽管能够应用库中的函数,然而当间接援用函数时零碎不主动援用@yunzhi
,须要人工手动引入。
询问之后发现只须要依据援用的文件名在package.json
中引入相应依赖,再从新执行npm install
即可。
之后又发现package.json中次要蕴含以下几种参数
"scripts":{...}"dependencies":{...}"devDependencies":{...}
其中 scripts:
定义了一组能够运行的 node 脚本。
"scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }
也就是平时用到的ng s,ng t等。
dependencies
设置了作为依赖装置的 npm
软件包的列表。
比方:
"@angular/animations": "~12.1.2", "@angular/common": "~12.1.2", "@angular/compiler": "~12.1.2", "@angular/core": "~12.1.2", "@angular/forms": "~12.1.2","@yunzhi/ng-common": "0.0.6", "@yunzhi/ng-mock-api": "0.0.9", "@yunzhi/ng-theme": "0.0.8", "@yunzhi/utils": "0.0.3"
这些都是为咱们的利用理论提供相应性能的依赖,也就是为MVC层提供服务的依赖。
devDependencies
设置了作为开发依赖装置的 npm
软件包的列表。
比方:
"karma": "~5.1.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage": "~2.0.3", "karma-jasmine": "~4.0.0", "@angular/cli": "~12.1.2", "@angular/compiler-cli": "~12.1.2", "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", "@yunzhi/ng-router-testing": "0.0.2",
这些依赖都是在开发时用于测试时所须要的依赖,理论产品中用户并不会用到这些依赖。
晓得了这些当前对于如何更改angular版本也就变得很简略,咱们只须要改变带有@angular的依赖的版本即可。
问题二:在增加mockApi时遇到的问题
对于目前的应用来说只须要增加 qpis.ts
, api.testing.modules
, api.demo.modules
。
其中 apis.ts
也就是一个蕴含有咱们所要用到的API的数组。
export const apis = [ UserApi, LogApi, ClientApi];
api.demo.module
用于ng s下脱离后盾跑demoapi.testing.module
用于进行单元测试。
providers: [ { provide: HTTP_INTERCEPTORS, multi: true, useClass: MockApiTestingInterceptor.forRoot(apis) }]
这是api.testing中的次要内容,通过MockApiTestingInterceptor
的forRoot
办法提供了HTTP_INTERCEPTORS
拦截器服务。
Angular在发动Http申请时,会查问以后模块是否有HTTP_INTERCEPTORS的提供者, 如果有则会应用该提供者对申请进行拦挡。
应用multi: true
来表时以后提供者为多个具备这种能力的一个(应用该计划保障了能够定义多个拦截器)。
static forRoot(mockApis: Type<MockApiInterface>[]): Type<HttpInterceptor>;
这是MockApiTestingInterceptor
中的forRoot
办法,接管一个API数组,返回一个HttpInterceptor
。
如图便是MockApi的机制
返还了HTTP_INTERCEPTORS
拦截器服务,拦挡到申请后就会依据forRoot
办法中的api
数组寻找相应的api
.
Api大抵格局
export class XxxApi implements MockApiInterface {protected url = 'xxx'getInjectors(): ApiInjector[] {return [{method: '',url: '',result: (urlMatches: string[], options: { params: HttpParams; }){}}]}}
其中urlMatches为申请URL的相干信息,options包含了承受的参数等信息。
至此,便能够实现拦挡申请并返回模仿数据的性能。
这是就又呈现了一个问题,为什么要在ng s中模仿返回数据不能像ng t中一样只增加一个MockApiTestingInterceptor
提供的拦截器
于是我尝试着在app.modules中援用ApiTestingModule
不援用ApiDemoModule
,测试后发现呈现了这样的报错 ——援用谬误:beforeAll没有被定义。
main.js:1 Uncaught ReferenceError: beforeAll is not defined
ApiDemoModule:
providers: [ { provide: HTTP_INTERCEPTORS, multi: true, useClass: LoadingInterceptor }, { provide: HTTP_INTERCEPTORS, multi: true, useClass: MockApiInterceptor.forRoot(apis) }]
它比ApiTestingModule多了一个LoadingInterceptor
拦截器:
export class LoadingInterceptor implements HttpInterceptor { public static loadingSubject = new Subject<boolean>(); public static loading$ = LoadingInterceptor.loadingSubject.asObservable(); public static ignoreKey = 'loading-ignore'; intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (req.params.has(LoadingInterceptor.ignoreKey)) { return next.handle(req); } else { LoadingInterceptor.loadingSubject.next(true); return next.handle(req).pipe(finalize(() => LoadingInterceptor.loadingSubject.next(false))); } }}
其中 Subject 是一个非凡的Observable,它反对将值传给其余很多的Observable,
req.params.has(xxx)是用来检索req.params中是否含有xxx,如果没有则返回null,
handel()将HttpRequest转换为HttpEvents流,使其传向下一个拦截器
finalize返回一个Observable,该Observable镜像源Observable,但当源在实现或出错时终止时将调用指定函数。
之后通过测试在ng s中触发的是
return next.handle(req).pipe(finalize(() => LoadingInterceptor.loadingSubject.next(false)));
也就是说如果申请的参数含有loading-ignore
阐明没有谬误,能够间接传向下一个拦截器,如果不含有则阐明有谬误,须要通过finalize
管道的解决,返回一个执行时没有谬误的Observable给下一个拦截器。