2017-08-16 8 views
2

これは簡単な問題だと確信していますが、それを特定する場所はわかりません。 私は、userdataのBehaviorSubjectを作成するUserProfileサービスを持っています。 私がログインすると、このサービスを使用してユーザデータをブロードキャストします。 ログインすると、私のDashbordコンポーネントのこのユーザーデータを購読します。しかし、私が最初にBehaviorSubjectを作成したとき、観測可能なuserdataは最初の空のオブジェクトを返すだけです。これは、.next()で新しいデータをプッシュするログイン関数が、BehaviourSubjectにサブスクライブしたダッシュボードの後でのみ実行されているかのようです。 .next()がサブスクリプションの前に実行されるように、ダッシュボードをngAfterContentInit()に登録しようとしましたが、空のオブジェクトがまだ残っています。私のダッシュボード内でset_new_data()関数を使って.next()を実行して観測可能な仕事があるかどうかを調べると、.next();によってデータが渡されます。しかし、私は私のログインコンポーネントが私のサービス内のset_userdata()関数によって設定されたデータを取得しません。角度動作サービスおよびコンポーネントでのオブジェクトの使用状況、競合状態の可能性

サービスを使用してこのようなデータを共有することはできませんか?ログインコンポーネントを終了した後、または何が起きているのか、サービスは破壊されていますか?

マイUSERPROFILEサービス:

@Injectable() 
export class UserProfileService { 
    public isLoggedIn: boolean = false; 
    public userdata: BehaviorSubject<any> = new BehaviorSubject<any>({}); 

    constructor() { 

    } 

    public set_userdata(data) { 
     // this.userdata = data; 
     console.log(this.userdata); 
     if (this.userdata === undefined) { 
      console.log(data); 
      //this.userdata = new BehaviorSubject<any[]>(data); 
      console.log(this.userdata); 
     } else { 
      console.log(this.userdata); 
      this.userdata.next(data); 
     } 

    } 
} 

マイDashbordコンポーネント:

@Component({ 
    selector: 'dashboard', 
    styleUrls: ['./dashboard.scss'], 
    templateUrl: './dashboard.html' 
}) 
export class Dashboard { 
    public isLoggedIn: boolean; 
    public curr_user: object; 

    constructor(private _appGlobals: AppGlobals, private _user: UserProfileService) { 
     this._appGlobals.isUserLoggedIn.subscribe(value => this.isLoggedIn = value); 
     // this.curr_user = _user.userdata; 
    } 

    ngAfterContentInit() { 
     console.log("this executes first"); 
     this._user.userdata.subscribe(value => { 
      this.curr_user = value; 
      console.log(value); 
     }); 
    } 

    set_new_data() { 
     let obj = { 
      name: "test", 
      age: 45 
     }; 
     this._user.userdata.next(obj); 
    } 
} 

マイコンソール出力は、(空のオブジェクトを示している:{}、ユーザーデータを期待)

enter image description here

+1

あなたは 'UserProfileService'をどこに提供しますか?なぜあなたはこの行をあなたの中でコメントアウトしていますか? '//this.userdata = new BehaviorSubject (data);'。完全に取り除いても安全です。新しいインスタンスを割り当てる必要はありません。これにより、すべてのサブスクリプションが無効になります。 –

+0

私はそれをLoginModuleとDashbordModuleに提供します。そのコメント行は、BSubjectを作成するときに最初のインスタンスに正しいデータを持たせようとしていたためです。 – johan

+0

これらのモジュールの1つが遅延ロードされていますか? BehaviorSubjectを初期化するには、 'this._userdata.next(someInitialValue);を呼び出してください。 –

答えて

1

あなたがあなたのサービスの単一のインスタンスだけを持っていることを確認し、そうでない場合は、加入者があなたとイベントを発行するために使用するものとは異なるBehaviorSubjectに加入することがあります。

コンポーネントにサービスを提供すると、このコンポーネントのインスタンスと同数のサービスインスタンスが作成される可能性があります。

複数のインスタンスを引き起こす可能性のある別の落とし穴は、独自のDIルートスコープを持つ遅延ロードされたモジュールです。
遅延ロードされていないモジュールのプロバイダは、アプリケーションルートスコープに持ち込まれます。同じサービスを提供する複数の遅延ロードされていないモジュールが存在する場合でも、インスタンスは1つだけです。

初期化後にDIスコープを更新できないため、レイジーロードされたモジュールからアプリケーションルートスコープにプロバイダを持ち込むことはできません。そのため、新しい "ルート"スコープが作成されます(アプリケーションルートの子スコープとして)スコープ、またはレイジーロードされた別の "ルート"スコープ)をロードすることができます。

forRootを使用すると、レイジーロードされたモジュールからアプリケーションルートスコープにプロバイダを追加できます。 https://angular.io/guide/ngmodule-faq#what-is-the-forroot-method
も参照してください。あるいは、AppModuleまたは直接遅延ロードされていないことが知られている他のモジュールでサービスを提供するだけです。

0

userdataをから返すとObservableとしてを入力し、Subjectの代わりにその関数にサブスクライブすると、コードが期待どおりに機能するはずです。ベストプラクティスについてはわかりませんが、

//UserProfileService 
public set_userdata(data) { //--> Maybe make this get_userdata() 
    // this.userdata = data; 
    console.log(this.userdata); 
    if (this.userdata === undefined) { 
     console.log(data); 
     console.log(this.userdata); 
    } else { 
     console.log(this.userdata); 
     this.userdata.next(data); 
    } 
    return this.userdata.asObservable(); 
} 

//Dashboard 
ngAfterContentInit() { //--> this could be in ngOnInit 
    console.log("this executes first"); 
    this._user.set_userdata().subscribe(value => { 
     this.curr_user = value; 
     console.log(value); 
    }); 
} 
+0

応答ありがとう、私は追加しました: 'public get_userdata(){ return this.userdata.asObservable(); } '私のuserProfileサービスでは、ログイン用にset_userdataを使用してデータを更新します。しかし、私のダッシュボード上にまだ空のオブジェクトがあります: 'this._user.get_userdata()。subscribe(value => { this.curr_user = value; console.log(value); }); – johan