[英]Angular 4/5 : Share data between Angular components
In my angular app, when I login in to the app, I get an access token which I need to use it in my API calls in other components (not parent/child relationship). 在我的角度应用程序中,当我登录到该应用程序时,我获得了一个访问令牌,我需要在其他组件的API调用中使用它(不是父/子关系)。 I tried using Shared service but it's not working
我尝试使用共享服务,但无法正常工作
Data Service: 数据服务:
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)
}
}
In my login component I have 在我的登录组件中,我有
this.dataService.updateUserInfo(data.userToken);
Other Component 其他成分
this.dataService.currentuserInfo$.subscribe((data: any) => {
console.log(data);
});
Here I am unable to get the tocken that was updated with the login component. 在这里,我无法获取使用登录组件更新的令牌。
In the shared Service I tried both Subject and Behavior Subject but both didn't work. 在共享服务中,我尝试了主题和行为主题,但是都没有用。
I made sure that I just mentioned this DataService as a provider only in app.module.ts. 我确保仅在app.module.ts中提到此DataService作为提供程序。 I didn't mentioned it in login component or in any other component
我没有在登录组件或任何其他组件中提到它
the best way to add token in requests is to use interceptor 在请求中添加令牌的最佳方法是使用拦截器
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));
}
}
UPDATED: 更新:
if you need to create a shareable service - you can try to use the behavior subject. 如果您需要创建可共享的服务-您可以尝试使用行为主题。 Please look at this example
请看这个例子
UPDATED2: UPDATED2:
if you want to use shareable data in spite of the page refreshing - you should use localstorage: 如果尽管页面刷新但仍要使用可共享的数据,则应使用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
Can you show how you have been using BahviorSubject and explain what means that this is not working? 您能说明一下您如何使用BahviorSubject并解释这意味着什么不起作用吗? I think that it should work.
我认为应该可以。
First, you need to declare it somewhere in the service, for example 首先,您需要在服务中的某个位置声明它,例如
token: BegaviorSubject<type> = new BehaviorSubject(null);
Then somewhere where you receive that token you need to set next 然后在您收到该令牌的地方,接下来需要设置
this.token.next(receivedToken);
And finally, subscribe to it form other components 最后,通过其他组件进行订阅
this.yourService.token.subscribe(token => {
this.token = token;
}
If you have some errors please show it. 如果您有任何错误,请显示出来。
@indira: As @JB Nizet has explained, on a page refresh, your whole application refreshes so whatever in your is contained in your subject, will be lost! @indira:正如@JB Nizet解释的那样,在页面刷新时,整个应用程序都会刷新,因此您主题中包含的所有内容都将丢失!
Now, a Simple subject should also have been working in your case, are you subscribing to the Subject inside a function which is definitely called? 现在,一个简单的主题在您的情况下也应该一直在工作,您是否在某个函数中订阅了Subject,该函数肯定被称为? for example inside
ngOnInit()
例如在
ngOnInit()
内部
ngOnInit() {
this.dataService.currentuserInfo$.subscribe((data) => {
console.log("data subscribed", data);
})
}
I tried on my machine and the above works fine. 我在我的机器上尝试过,以上工作正常。
Why was Subject not working? 为什么主题不起作用?
A possible reason for the Simple Subject
to fail could be: You are just testing the functionality of the Subject and not doing an actual login. 简单
Subject
失败的可能原因可能是:您只是测试主题的功能而未进行实际登录。 And in your scenario, your login
component is loading before other components which have actually done the subscription. 在您的方案中,您的
login
组件将在实际完成订阅的其他组件之前加载。 But wait: If you have already pushed new data to the Subject before it has been subscribed, you won't get the data in the subscription. 但是请稍等:如果您已在订阅之前将新数据推送到主题,则不会在订阅中获取数据。 Only after the next
this.dataService.updateUserInfo(data.userToken)
, you will get the values in the Subscription. 仅在下一个
this.dataService.updateUserInfo(data.userToken)
,您才可以在订阅中获取值。 If this is the case, then you can definitely use the BehaviorSubject
. 如果是这种情况,那么您绝对可以使用
BehaviorSubject
。
As far as saving the state of the Subject is concerned, you have options like: cookies
, localstorage
. 就保存主题的状态而言,您可以选择以下选项:
cookies
, localstorage
。
for example: when you are updating the Subject from your login component, store the data in localstorage
: 例如:从登录组件更新主题时,将数据存储在
localstorage
:
this.dataService.updateUserInfo(data.userToken)
localStorage.setItem('serviceData', String(data.userToken));
And then apart from listening to the Subject in your other components, you can also take out the value of the token localStorage.getItem('serviceData')
upon ngOnInit()
然后,除了侦听其他组件中的Subject之外,您还可以根据
ngOnInit()
令牌localStorage.getItem('serviceData')
的ngOnInit()
I myself prefer localStorage over cookies. 我自己更喜欢localStorage而不是cookie。 Cookies have a size and a number limit per domain.
Cookie在每个域中都有大小和数量限制。 See this link for more info .
有关更多信息,请参见此链接 。 Even
localStorage
has a size limit, but that's huge. 即使
localStorage
也有大小限制,但这是巨大的。 Using cookies or localStorage can also be clear from this SO question. 从这个SO问题也可以很清楚地使用cookie或localStorage 。 You can analyze your requirement and implement either of them.
您可以分析您的需求并实现它们中的任何一个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.