Angular: дождитесь возвращения одного наблюдаемого, чтобы инициировать другое - PullRequest
0 голосов
/ 27 ноября 2018

Мой бизнес-сценарий выглядит следующим образом: сначала я отправляю HTTP-запрос к конечной точке token () в WebAPI для получения токена авторизации (это происходит в app.component.ts).Затем у меня есть модуль токена-перехватчика для добавления токена в заголовки HTTP последующих запросов.

Затем у меня есть конечная точка getLanguages ​​() в WebAPI, и она вызывается в моем компоненте заголовка - заголовке.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);
 }

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Вы можете сохранить свою информацию токена в BehaviorSubject внутри AuthService.

Затем вызвать .next(token) при authenticateClient() успехе.

В 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);

В приведенном выше коде вы создаете новую Observable из authService, когда кто-то запускает next на токене BehaviorSubject, эта наблюдаемая проверяет, определен ли токен, и если это так, выможет вызвать ваш внутренний API.

Это способ, но я думаю, что есть и другие решения.

0 голосов
/ 27 ноября 2018

Вы можете использовать Promise для того же.

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

});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...