繁体   English   中英

角度:等待一个可观察到的返回以发起另一个

[英]Angular: wait for the return of one observable to initiate the other

我的业务场景是这样的:我首先向WebAPI中的token()端点发出HTTP请求以获取auth令牌(这发生在app.component.ts中)。 然后,我有一个令牌拦截器模块,将令牌附加到后续请求的HTTP标头中。

然后,我在WebAPI中有一个getLanguages()端点,并且在我的标头组件header.component.ts中调用了该端点。 因此,此调用通过HTTP侦听器,尝试将生成的令牌附加到请求标头,但是由于token()端点尚未返回,因此失败,因此getLanguages()端点未通过身份验证。

我显然在这里错过了一些东西。 我读过有关ReplaySubject但不确定如何将所有内容放在一起。

这是我当前的代码。

app.component.html:

<app-header>
</app-header>
<router-outlet></router-outlet>
<app-footer>
</app-footer>

auth.service.ts:

 authenticateClient(){

let body = new HttpParams()
  .set('client_id', AppConst.GLOBAL.auth.client_id)
  .set('grant_type', AppConst.GLOBAL.auth.grant_type)
  .set('scope', AppConst.GLOBAL.auth.scope);

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/x-www-form-urlencoded'
  })
};

let authGatewayUrl: string = AppConst.GLOBAL.authApiUrl + window.location.search;

return this.http.post(authGatewayUrl, body.toString(), httpOptions)
          .pipe(map((res: any) => this.token = res), catchError(this.handleErrorObservable));
      }

  getToken(): Token {
    return this.token;
  }

app.component.ts:

token: Token;

 ngOnInit() {
// get the authentication token and store it for usage in subsequent API calls.
this.authService.authenticateClient().subscribe(
  obj => this.token = obj as Token,
  err => alert(err)
  );
  }

app.service.ts:

  getLanguages() {
 return this.http.get(this.localeApiUrl)
  .pipe(map((res: any) => this.languages = res), catchError(this.handleErrorObservable));
  }

header.component.ts:

   constructor(private appService: AppService) {
    this.appService.getLanguages().subscribe(obj => this.languages = obj);

  };

http-interceptor.ts:

intercept(req: HttpRequest<any>, next: HttpHandler) {
// exclude the token API endpoint from the interception
const loginUrl: string = AppConst.GLOBAL.authApiUrl;

if (req.url.search(loginUrl) === -1) {
  // Get the auth token from the service.
  const authToken = this.auth.getToken();

  //// Clone the request and set the new header in one step.
  req = req.clone({ setHeaders: { Authorization: authToken.access_token } });
}

//// send cloned request with header to the next handler.
return next.handle(req);
 }

你可以节省您的令牌信息在BehaviorSubject的AuthService内。

然后在authenticateClient()成功时触发.next(token)

header.component ,您可以这样做。

  readonly languages$ = this.authService.token$.pipe(
    first(!!token), // or filter, depends on your application logic
    switchMap(() => this.appService.getLanguages(),
  );

  this.languages$.subscribe(obj => this.languages = obj);

在上面的代码中,您将从authService创建一个新的Observable,当有人在令牌BehaviorSubject上触发next一个触发时,该Observable将检查是否已定义令牌,如果已定义,则可以调用内部API。

这是一种方法,但是我认为还有其他解决方案。

您可以使用Promise。

var promise = new Promise((resolve, reject) => {
setTimeout(() => {
  console.log("Async Work Complete");
  if (error) {
    reject();
  } else {
    resolve();
  }
}, 1000);

});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM