Summary of some problems encountered this week

Question 1: how to reference private libraries
At first, I thought that since node_modules are used to store the installed packages, so put @ yunzhi directly into the node_modules.
After trying, it is found that although functions in the library can be used, when functions are directly referenced, the system does not automatically reference @yunzhi, and manual introduction is required.
After inquiry, it is found that only the referenced file name is required in package JSON, and then re execute npm install.
Then I found package JSON mainly contains the following parameters


Scripts: defines a set of node scripts that can be run.

"scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"

That is, ng s,ng t, etc.

Dependencies sets the list of npm packages installed as dependencies.
For example:

"@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"

These are the dependencies of providing corresponding functions for our applications, that is, the dependencies of providing services for the MVC layer.

devDependencies sets the list of npm packages installed as development dependencies.
For example:

"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",

These dependencies are needed for testing during development. Users will not use these dependencies in actual products.

After knowing this, it becomes very simple to change the version of angular. We only need to change the version with @ angular dependency.

Problem 2: problems encountered when adding mockApi
For current use, you only need to add qpis ts, api. testing. modules, api. demo. modules.
Where APIs TS is an array containing the APIs we need to use.

export const apis = [

api.demo.module is used to run the demo away from the background under ng s
api.testing.module is used for unit testing.

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

This is the API The main content of testing provides HTTP through the forRoot method of MockApiTestingInterceptor_ Interceptors interceptor service.
When initiating an Http request, Angular will query whether the current module has Http_ The provider of interceptors, if any, will be used to intercept requests.
When using multi: true to the table, the current provider is multiple one with this capability (using this scheme ensures that multiple interceptors can be defined).

static forRoot(mockApis: Type<MockApiInterface>[]): Type<HttpInterceptor>;
This is the forRoot method in MockApiTestingInterceptor. It receives an API array and returns an HttpInterceptor.

The mechanism of MockApi is shown in the figure

HTTP returned_ The interceptors interceptor service will find the corresponding api according to the api array in the forRoot method after intercepting the request

Api approximate format

export class XxxApi implements MockApiInterface {
protected url = 'xxx'
getInjectors(): ApiInjector[] {
return [{
method: '',
url:  '',
result: (urlMatches: string[], options: { params: HttpParams; }){}

Where urlMatches is the relevant information of the request URL, and options includes the accepted parameters and other information.
At this point, the function of intercepting requests and returning simulated data can be realized.
This is another problem. Why do you want to simulate the return data in ng s? You can't just add an interceptor provided by MockApiTestingInterceptor as in ng t
So I tried on the app Modules refer to ApiTestingModule instead of ApiDemoModule. After testing, it is found that such an error occurs - reference error: beforeAll is not defined.

main.js:1 Uncaught ReferenceError: beforeAll is not defined


providers: [
      provide: HTTP_INTERCEPTORS, multi: true, useClass: LoadingInterceptor
      provide: HTTP_INTERCEPTORS, multi: true, useClass: MockApiInterceptor.forRoot(apis)

It has one more LoadingInterceptor interceptor than ApiTestingModule:

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 {;
      return next.handle(req).pipe(finalize(() =>;


Subject is a special Observable, which supports passing values to many other observables,
req.params.has(xxx) is used to retrieve req Whether the params contains XXX. If not, null will be returned,
handel() converts HttpRequest into an HttpEvents stream and passes it to the next interceptor
finalize returns an Observable that mirrors the source Observable, but the specified function will be called when the source terminates on completion or error.
After testing, the trigger in ng s is

return next.handle(req).pipe(finalize(() =>;

That is, if the requested parameter contains loading ignore, it indicates that there is no error, it can be directly passed to the next interceptor. If it does not, it indicates that there is an error, which needs to be processed through the finalize pipeline, and an Observable without error during execution is returned to the next interceptor.

Keywords: angular npm

Added by PlasmaDragon on Wed, 05 Jan 2022 16:58:52 +0200