乐趣区

关于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 给下一个拦截器。

退出移动版