Angular 获取 - 地图中的地图

Angular get - map inside map

我正在尝试调用 map 中的 API 方法,但从未进行过第二个 API 调用。没有控制台错误。

//This method is not being called - Not hitting the API method
this.getUserPermissions(localStorage.getItem('user_ref'));

只是想知道我是否不能在 map 中调用 map?

下面是我的代码。

  public isAuthenticated() {

    if (!this.loggedIn)
      this.redirectToLogin();

    return this.httpClient.get<boolean>(`${this.settings.getApiSettings('uri')}/api/auth/IsTokenValid`, {
      params: { token: this.getToken }
    }).map( /// <<<=== use `map` here
      (response) => {

        if (response !== null) {

          var receivedToken = response["securityStamp"];
          var availableToken = localStorage.getItem('access_token');

           //Check if received a refreshed token. (tokens are refreshed every 15 minutes)
          if (receivedToken && receivedToken !== availableToken) {

            localStorage.removeItem('access_token');
            localStorage.setItem('access_token', response["securityStamp"]);

          }

           this.user_permissions = this.getUserPermissions(localStorage.getItem('user_ref'));


        }

        let data = response;
        if (data == null)
          return false;
        else
          return true;

      }
    );

  }

  getUserPermissions(user_ref) {

    if (!this.loggedIn)
      this.redirectToLogin();

    const httpParams: HttpParamsOptions = { userRef: "44C4D2F7-76A0-4714-B8CA-3123F607AC5A" } as HttpParamsOptions;

    const httpOptions = {
      params: new HttpParams(httpParams),
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + this.getToken
      })
    };

    return this.httpClient.get<Array<any>>(`${this.settings.getApiSettings('uri')}/api/auth/GetUserPermissions`, httpOptions).map( /// <<<=== use `map` here
      (response) => {

        if (response["status"] == 401) {
          this.redirectToLogin();
        }
        else if (response["status"] < 200 || response["status"] >= 300) {
          throw new Error('This request has failed ' + response["status"]);
        }

        this.user_permissions = response;
        return response;
      }
    );

  }

那是因为 .map() 函数不是 return 订阅而是可观察的。 如果您需要与来自 HttpClient 的 api 调用的响应进行交互,那么您需要订阅您正在调用的 .get().post() 方法。

这可能会满足您的需要,或者至少在控制台中记录它以防请求失败。

firstUrl = `${this.settings.getApiSettings('uri')}/api/auth/IsTokenValid`;
secondUrl = `${this.settings.getApiSettings('uri')}/api/auth/GetUserPermissions`;

public isAuthenticated() {

    if (!this.loggedIn) this.redirectToLogin();
    return this.httpClient.get<boolean>(this.firstUrl, {params: {token: this.getToken}}).subscribe(
        (response) => {
            if (response !== null) {
                let receivedToken = response["securityStamp"];
                let availableToken = localStorage.getItem('access_token');
                if (receivedToken && receivedToken !== availableToken) {
                    localStorage.removeItem('access_token');
                    localStorage.setItem('access_token', response["securityStamp"]);
                }
                this.user_permissions = this.getUserPermissions(localStorage.getItem('user_ref'));
            }
            return response != null;
        },
        (error) => console.log(error)
    );
}

getUserPermissions(user_ref) {
    if (!this.loggedIn) this.redirectToLogin();
    const httpParams: HttpParamsOptions = {userRef: "44C4D2F7-76A0-4714-B8CA-3123F607AC5A"} as HttpParamsOptions;
    const httpOptions = {
        params: new HttpParams(httpParams),
        headers: new HttpHeaders({
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + this.getToken
        })
    };
    return this.httpClient.get<Array<any>>(this.secondUrl, httpOptions).subscribe(
        (response) => {
            if (response["status"] == 401) {
                this.redirectToLogin();
            } else if (response["status"] < 200 || response["status"] >= 300) {
                throw new Error('This request has failed ' + response["status"]);
            }
            this.user_permissions = response;
            return response;
        },
        (error) => console.log(error)
    );
}

您使用的是什么版本的 Angular(更重要的是 rxjs)?

记住 HttpClient returns 和 Observable(一个懒惰的 observable,在您订阅它之前不会做任何事情)。

https://angular.io/guide/http

作为您的 isAuthenticated 方法 returns 一个 HttpClient Get 方法,您的 isAuthenticated returns 一个等待订阅的可观察对象。

订阅 HttpClient observable 将进行 http 调用,在收到响应时调用观察者下一个处理程序,如果提供,也会调用 on complete 处理程序。我建议在这里阅读 Observables。 https://www.learnrxjs.io/

// Doing this will not do anything as the observable has not been subscribed to.
this.httpClient.get<boolean>(`...`);

// Subscribing to the HttpClient will make the request
this.httpClient.get<boolean>(`...`)
    .subscribe((response) => {

      // do something with the response

});

正如您所说的第一个 HttpCall 已创建,我假设您在调用它时订阅了 isAuthenticated 方法?即

isAuthenticated().subscribe( (response) => {
 //
})

请注意,您的 getUserPermissions 也 returns 一个 HttpClient 方法(一个可观察的),但是当您调用它时 this.getUserPermissions(localStorage.getItem('user_ref')); 它从未被订阅,因此从未被调用。

要发起第二个请求,您必须订阅 getUserPermissions 调用,如下所示。

public isAuthenticated() {

    // ...

    return this.httpClient.get<boolean>('...').map(
      (response) => {

           // Subscribe to the second Http call

           this.getUserPermissions(localStorage.getItem('user_ref'))
             .subscribe( (response) => {
               // do something with the second
           })
       })
}

一些旁注; 从 rxjs v6 开始,您链接到 httpClient.get 方法的 map 运算符已被弃用,取而代之的是管道运算符。

参见:https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md

所以这个

this.httpClient.get<boolean>('...')
    .map( ... )
    .subscribe(...)

现在应该这样写:

this.httpClient.get<boolean>('...')
  .pipe(        // <- Pipe the operators
    map( ... ),
    map( ... )
  )
  .subscribe( ...)

尽管在原始问题之外,我会考虑重构您的代码并使用可用的 rxjs/operators 来实现更好的流程控制。

this.httpClient.get<boolean>('...')
    .pipe(       
      map(( response ) => {
        // some logic
        return something;
      }),
      map( (something) => localStorage.getItem('user_ref')),
      switchMap( (userRef) => this.getUserPermissions(userRef)), // <- switchMap to a new observable
    )
    .subscribe( (responseFromGetUserPermissions) => {
       // This value is now the return of getUserPermissions because of switchMap

    })

rxjs / observable 是一个非常强大的模式,我强烈建议花大量时间学习如何充分利用它们。

问候 乔诺

当然你可以在地图中调用地图,但是这里你没有调用 API 的问题是因为你的方法 "getUserPermissions" 返回的是 Observable 而不是用户的数据。

我建议您按照反应式方法更改这部分的设计。

你可以阅读这个link

希望对你有帮助