关于angular:本周遇到的一些问题汇总

问题一:如何援用公有库
起初认为既然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给下一个拦截器。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理