簡體   English   中英

Angular 4/5:在Angular組件之間共享數據

[英]Angular 4/5 : Share data between Angular components

在我的角度應用程序中,當我登錄到該應用程序時,我獲得了一個訪問令牌,我需要在其他組件的API調用中使用它(不是父/子關系)。 我嘗試使用共享服務,但無法正常工作

數據服務:

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';

@Injectable()
export class DataService {

  private userInfo = new Subject<any>();
  currentuserInfo$ = this.userInfo.asObservable();

  constructor() { }

  updateUserInfo(message: any) {
    this.userInfo.next(message)
  }

}

在我的登錄組件中,我有

this.dataService.updateUserInfo(data.userToken);

其他成分

this.dataService.currentuserInfo$.subscribe((data: any) => { 
  console.log(data);
});

在這里,我無法獲取使用登錄組件更新的令牌。

在共享服務中,我嘗試了主題和行為主題,但是都沒有用。

我確保僅在app.module.ts中提到此DataService作為提供程序。 我沒有在登錄組件或任何其他組件中提到它

在請求中添加令牌的最佳方法是使用攔截器

import { Injectable, Injector, EventEmitter } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../services/auth.service';

@Injectable()
export class HttpsRequestInterceptor implements HttpInterceptor {
    private actionUrl: string;

    constructor(
        private injector: Injector
    ) {
        this.actionUrl = 'https://test.com/dev';
    }


    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const _req = {
            url: this.actionUrl + req.url,
            headers: req.headers.set('Content-Type', 'application/json')
        };

        const user = this.injector.get(AuthService).getAuthenticatedUser();

        if (user) {
            user.getSession((err: any, session: any) => {
                if (session) {
                    const token = session.getIdToken().getJwtToken();
                    _req.headers = req.headers
                        .set('Content-Type', 'application/json')
                        .set('Authorization', token);
                }
            });
        }

        return next.handle(req.clone(_req));
    }
}

更新:

如果您需要創建可共享的服務-您可以嘗試使用行為主題。 請看這個例子

UPDATED2:

如果盡管頁面刷新但仍要使用可共享的數據,則應使用localstorage:

localStorage.setItem('str', 'whatever string'); // set string
localStorage.setItem('obj', JSON.stringify(obj)); // set object
const str = localStorage.getItem('str'); // get string
const obj = JSON.parse(localStorage.getItem('obj')); // get object
const str = localStorage.removeItem('str'); // remove 

您能說明一下您如何使用BahviorSubject並解釋這意味着什么不起作用嗎? 我認為應該可以。

首先,您需要在服務中的某個位置聲明它,例如

token: BegaviorSubject<type> = new BehaviorSubject(null);

然后在您收到該令牌的地方,接下來需要設置

this.token.next(receivedToken);

最后,通過其他組件進行訂閱

this.yourService.token.subscribe(token => {
   this.token = token;
}

如果您有任何錯誤,請顯示出來。

@indira:正如@JB Nizet解釋的那樣,在頁面刷新時,整個應用程序都會刷新,因此您主題中包含的所有內容都將丟失!

現在,一個簡單的主題在您的情況下也應該一直在工作,您是否在某個函數中訂閱了Subject,該函數肯定被稱為? 例如在ngOnInit()內部

ngOnInit() {
    this.dataService.currentuserInfo$.subscribe((data) => {
      console.log("data subscribed", data);
    })
}

我在我的機器上嘗試過,以上工作正常。

為什么主題不起作用?

簡單Subject失敗的可能原因可能是:您只是測試主題的功能而未進行實際登錄。 在您的方案中,您的login組件將在實際完成訂閱的其他組件之前加載。 但是請稍等:如果您已在訂閱之前將新數據推送到主題,則不會在訂閱中獲取數據。 僅在下一個this.dataService.updateUserInfo(data.userToken) ,您才可以在訂閱中獲取值。 如果是這種情況,那么您絕對可以使用BehaviorSubject

就保存主題的狀態而言,您可以選擇以下選項: cookieslocalstorage

例如:從登錄組件更新主題時,將數據存儲在localstorage

this.dataService.updateUserInfo(data.userToken)
localStorage.setItem('serviceData', String(data.userToken));

然后,除了偵聽其他組件中的Subject之外,您還可以根據ngOnInit()令牌localStorage.getItem('serviceData')ngOnInit()

我自己更喜歡localStorage而不是cookie。 Cookie在每個域中都有大小和數量限制。 有關更多信息,請參見此鏈接 即使localStorage也有大小限制,但這是巨大的。 從這個SO問題也可以很清楚地使用cookie或localStorage 您可以分析您的需求並實現它們中的任何一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM