问题一:如何援用公有库
起初认为既然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下脱离后盾跑demo
api.testing.module用于进行单元测试。

providers: [    {      provide: HTTP_INTERCEPTORS, multi: true, useClass: MockApiTestingInterceptor.forRoot(apis)    }]

这是api.testing中的次要内容,通过MockApiTestingInterceptorforRoot办法提供了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给下一个拦截器。