web-dev-qa-db-ja.com

angular 2で観測可能な変数を設定する

私たちがやりたいのは、サイトの複数のセクションで使用できる2つの変数を返すURLからエンドポイントを呼び出すことです。 http呼び出しを使用してサブスクライブしていますが、サイトを高速化するために、api呼び出しを1回だけ実行する必要があります。これを行うために、サービス上にObservableを作成しました。サービスは、Observableの値を設定するコンストラクター内の関数を呼び出しますが、リンクに直接アクセスすると、undefinedのメソッドにサブスクライブできないことが返される場合があります。これは、MicrosoftADALライブラリのサンプルコードを使用しています。

最初に、サービスでObservableとして変数を設定しています:

@Injectable()
export class MicrosoftGraphService {
  public details: Observable<any>;

次に、コンストラクターで監視可能な値を設定します:

constructor(
private _http:Http,
private _adalService: AdalService,
private _sanitizer:DomSanitizer
) {

this.getToken().subscribe(token => {
  /**
   * Get me data from graph to determine school_id and mis_id
   */
  this.get('me', token, true).subscribe(me => {
    this.details = new Observable(observer => {
        observer.next({
          me: me
        });
        observer.complete();
    });
  });
});

getToken関数は次のとおりです:

getToken(): Observable<any> {
    return this._adalService
      .acquireToken( this._adalService.config.endpoints.graph );
}

get関数は:

get( endpoint, token, beta = false ): Observable<any>  {
  return this._http.get( this._adalService.config.endpoints.graph + 
    this.getVersion( beta ) + endpoint, {
      headers: new Headers({ "Authorization": "Bearer " + token })
    })
    .map(res => {
      return res.json();
    });
}

これは、コンポーネントのコンストラクターで次のように呼び出されます:

this._microsoftGraph.details.subscribe(details => {
    console.log(details);
});

これにより、meエンドポイントの戻りのコンソールログが追加されますが、特定のページでは追加され、他のページではundefinedにサブスクライブできません。 MicrosoftGraphServiceが呼び出され、両方のページのコンストラクターで正しく設定されます。

これは、呼び出された方法と設定されたタイミングが原因で発生するのではないかと思います。ベースURLにアクセスすると、親コンポーネントが呼び出されます。これは、コンストラクターでMicrosoftGraphServiceが呼び出されるため、最初に初期化されるため、ナビゲーションを介して2番目のコンポーネントにアクセスするときに使用できます。ただし、子コンポーネントのURLの場所に直接移動すると、両方がMicrosoftGraphServiceをロードしている場合でも、親の前に最初に呼び出される可能性があります。

役立つ場合のルートの例:

const routes: Routes = [
{
    path: '',
    component: SiteComponent,
canActivate: [LoggedInGuard],
children: [
    { path: 'dashboard', component: DashboardComponent },
    { path: 'tasks', component: TasksComponent },
    {
      path: '',
      redirectTo: '/dashboard'
      , pathMatch: 'full'
      // , terminal: true
    }
  ]
},
5
user1468867

問題は、_public details: Observable<any>;_が最初に初期化されておらず、サブスクリプションでgetToken()に渡すときに、を使用して毎回新しいObservableに設定することです。

_this.details = new Observable(observer => {
    observer.next({
      me: me
    });
    observer.complete();
});
_

このため、コンポーネントは、detailsにアクセスするときに、アクセスする時点に応じて、異なるオブジェクトを取得します。

私はあなたのサービスで次のようなことをすることを提案します:

_detailsSubject = new Subject<any>();
public details = this.detailsSubject.asObservable();

// --- in your subscription where you set your Observable before
this.detailsSubject.next(/* here comes your token */);
_

詳細については、これを見てください

7
alex kucksdorf