映射函数完成订阅句柄后的Angular2 rxjs map()

时间:2017-01-19 21:24:21

标签: angular rxjs

我正在尝试更好地处理RXJS,但当我调用AudienceService.addAudience()时,我得到Cannot read property 'map' of undefined

问题似乎是当需要令牌刷新时,AudienceService会在AuthHttpService.post()内的订阅完成之前尝试映射到AuthHttpService.post()

我如何为此编码,并确保map()仅在AuthHttpService刷新令牌后才执行?

映射到AuthHttpService.post的AudienceService:

addAudience(model: AddDeleteAudienceModel) {
    return this.authHttpService.post(this.baseApiUrl + 'audience', JSON.stringify(model)).map(res => res.json());
  }

使用POST方法的AuthHttpService:

post(endpoint: string, body: string) {
    if (this.authService.tokenRequiresRefresh()) {
      this.authService.tokenIsBeingRefreshed.next(true);
      this.authService.refreshToken().subscribe(
        data => {
          this.authService.refreshTokenSuccessHandler(data);
          // The audience service post call returns "Cannot read property 'map' of undefined"
          console.log("User is now logged in");
          if (this.authService.loggedIn()) {
            this.authService.tokenIsBeingRefreshed.next(false);
            return this.postInternal(endpoint, body);
          } else {
            this.authService.tokenIsBeingRefreshed.next(false);
            this.router.navigate(['/sessiontimeout']);
          }
        },
        error => {
          this.authService.refreshTokenErrorHandler(error);
          Observable.throw(error);
        }
      );
    }
    else {
      console.log("HTTP Post token refresh not required.");
      return this.postInternal(endpoint, body);
    }
  }

2 个答案:

答案 0 :(得分:4)

如前所述,post()在需要刷新令牌时不会返回任何内容。在刷新令牌之前函数返回时,将不会调用return方法中的subscribe()语句。

您应该使用switchMap()代替subscribe来电。在这种情况下,您还需要从else块中返回一个Observable。像这样:

post(endpoint: string, body: string) {
    if (this.authService.tokenRequiresRefresh()) {
      this.authService.tokenIsBeingRefreshed.next(true);
      return this.authService.refreshToken().switchMap(
        data => {
          this.authService.refreshTokenSuccessHandler(data);
          // The audience service post call returns "Cannot read property 'map' of undefined"
          console.log("User is now logged in");
          if (this.authService.loggedIn()) {
            this.authService.tokenIsBeingRefreshed.next(false);
            return this.postInternal(endpoint, body);
          } else {
            this.authService.tokenIsBeingRefreshed.next(false);
            this.router.navigate(['/sessiontimeout']);
            // return an Observable here otherwise you also get an undefined
          }
        })
        .catch((error) => {
            this.authService.refreshTokenErrorHandler(error);
            return Observable.throw(error);
        });
    }
    else {
      console.log("HTTP Post token refresh not required.");
      return this.postInternal(endpoint, body);
    }
  }

有关switchMap()的更多信息。它基本上将内部Observable的值映射到外部Observable。

答案 1 :(得分:1)

在Post中你需要返回observable。我不确定100%这是否有效,但想法是你创建了observable并返回它,而不是你在逻辑内部。您可以发出next,或抛出异常

post(endpoint: string, body: string) {
    if (this.authService.tokenRequiresRefresh()) {
        this.authService.tokenIsBeingRefreshed.next(true);
        return Observable.create((observer) => {
            this.authService.refreshToken().subscribe(
                data => {
                    this.authService.refreshTokenSuccessHandler(data);
                    // The audience service post call returns "Cannot read property 'map' of undefined"
                    console.log("User is now logged in");
                    if (this.authService.loggedIn()) {
                        this.authService.tokenIsBeingRefreshed.next(false);
                        this.postInternal(endpoint, body).subscribe(resp => {
                            observer.next(resp);
                        })

                    } else {
                        this.authService.tokenIsBeingRefreshed.next(false);
                        this.router.navigate(['/sessiontimeout']);
                        observer.error(error);
                    }
                },
                error => {
                    this.authService.refreshTokenErrorHandler(error);
                    observer.error(error);
                }
            );
        });


    }
    else {
        console.log("HTTP Post token refresh not required.");
        return this.postInternal(endpoint, body);
    }
}

我已经测试了我的应用

的一部分
return Observable.create(observer => {
        (<Promise<string>>token)
          .then((tAsString) => {
            super.request(this.getRequestOptionArgs(tAsString, request))
              .subscribe(response => {
                observer.next(response);
                // this emit error observer.error(eror)
              })

          })
      });

PS。但我的事情是switchMap是更好的选择:)