无法通过angular2中的服务传递数据
Cannot pass data with service in angular2
PS:
When I talk to my colleague, they told me to get Role's right with
once request, if it is not authenticated then reject, else return the
data to frond-end. But, I got stuck in use Angular2's Guard.
应用程序:
- 访问我的路由,
Guard
阻止它,Guard 向服务器发送请求以检查其身份验证。
- 请求
server
,当服务器returnstatue:true
和data:[somedatas]
然后用模块的dataService设置数据,并解析true
可以激活。
- 初始化目标组件,在
constructor
中,使用dataService
获取元数据。
但是,我未能将数据从 Guard 传递到 Service。我在同一个模块中提供它们。这是我的代码:
Module.ts:
@NgModule({
declarations: [
DocsComponent,
DocsListComponent, // this is the component I will access
BarButtonsComponent
],
imports: [
CommonModule,
DocsRouting,
// ShareModule
],
providers:[
DocsGuard,
DocsDataService // here I provide my dataService that I mentioned before
],
exports: [DocsComponent],
})
路线:
const DOCS_ROUTES:Routes = [
{path:'',redirectTo:'doclist',pathMatch:'full'},
{path:'',component:DocsComponent,children:[
{path:'doclist', component: DocsListComponent}
], canActivate:[DocsGuard] } // use `Guard` to prevent it.
];
我的dataService.ts:
private doclist:Doclist[] ; // this
getData(){
return this.doclist;
}
setData(obj){
this.doclist = obj;
}
getDocAuth(): Observable<any>{
let options = new RequestOptions({
withCredentials:true
});
// ...using get request
return this.http.get(this.docUrl,options)
// ...and calling .json() on the response to return data
.map((res:Response) =>res.json())
//...errors if any
.catch((error:any) => {
console.log(error)
})
}
Guard.ts:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>{
let subject = new Subject<boolean>();
let that = this;
this.docsDataService.getDocAuth().subscribe(
res=>{
if(res.status){
// Here I want to pass data to my component, I failed.
that.docsDataService.setData(res.data);
subject.next(true);
}else{
subject.next(false);
}
console.log("next: returning true");
},
err => {
console.log(err);
subject.next(false);
}
);
return subject.asObservable().first();
}
谢谢。
======================补充 2017-02-17 17:34============== ========
应用模块路由:
const APP_ROUTERS:Routes = [
{ path:'',component:JwLoginComponent},
{ path:'main',loadChildren:'app/main/main.module#MainModule'},
{ path:'**', component: PageNotFoundComponent }
];
主要路线:
const MAIN_ROUTES : Routes = [
{path:'main',component:MainComponent,canActivate:[DataGuard]},
{path:'share',loadChildren:'app/common/share.module#ShareModule'}
];
分享路线:
const SHARE_ROUTES:Routes = [
{path:'',redirectTo:'docs',pathMatch:'full'},
{path:'',component: ShareComponent,children:[
{ path:'docs',loadChildren:'app/docs/docs.module#DocsModule'},
// Question here: cannot get data from service set in DocsModule, but in MainModule or AppModule as providers.
{ path:'mic',loadChildren:'app/mic/mic.module#MicModule'},
{ path:'user-manage',loadChildren:'app/user-manage/user-manage.module#UserManageModule'},
{ path:'settings',loadChildren:'app/settings/settings.module#SettingsModule'},
{ path:'logs',loadChildren:'app/logs/logs.module#LogsModule'}
]},
];
我发现我在MainModule或AppModule中提供了DocService
,我可以从@mxii代码中获取数据。但是,当我将此服务设置为 DocsModule 或 ShareModule 时,我无法获取数据。
这个演示应该有帮助:
@Injectable()
export class DataService {
public data = new BehaviorSubject<any>(null);
public setData(data: any) {
this.data.next(data);
}
}
@Injectable()
export class AuthService {
public validate(user, pass): Observable<any> {
return Observable.of({ test: 'data' }).delay(123);
}
}
@Injectable()
export class DocsGuard implements CanActivate {
constructor(private _authService: AuthService, private _dataService: DataService) {}
canActivate() {
return this._authService.validate('user', 'pass').map(data => {
console.log('GUARD: auth data:', data);
// .. do something ..
if (!data || data.anyThing === 'anyValue') {
console.log('GUARD: auth WRONG');
return false; // not authenticated !
}
console.log('GUARD: auth OKAY, set data..');
this._dataService.setData(data);
return true;
})
.catch(err => {
console.log(err);
return Observable.of(false); // protect route !
});
}
}
@Component({
selector: 'my-comp',
template: `
{{ _data | async | json }}
`,
})
export class DocsListComponent {
private _data: BehaviorSubject<any>;
constructor(private _dataService: DataService) { }
ngOnInit() {
this._data = this._dataService.data;
this._data.subscribe(data => {
console.log('DocsListComponent: something changed', data);
});
}
}
现场演示:https://plnkr.co/edit/PGsTD3Ma9yDidhxEgot3?p=preview
更新
您的服务应该只包含 ONCE!!
您必须 provide
您的服务到 "highest" NgModule。
否则每个 NgModule 都会创建一个新的服务实例..
如果只有一个 NgModule provided
,它就是一个单例!
也许您必须像 RouterModule 那样创建 forRoot
和 forChild
等函数。
PS:
When I talk to my colleague, they told me to get Role's right with once request, if it is not authenticated then reject, else return the data to frond-end. But, I got stuck in use Angular2's Guard.
应用程序:
- 访问我的路由,
Guard
阻止它,Guard 向服务器发送请求以检查其身份验证。 - 请求
server
,当服务器returnstatue:true
和data:[somedatas]
然后用模块的dataService设置数据,并解析true
可以激活。 - 初始化目标组件,在
constructor
中,使用dataService
获取元数据。
但是,我未能将数据从 Guard 传递到 Service。我在同一个模块中提供它们。这是我的代码:
Module.ts:
@NgModule({
declarations: [
DocsComponent,
DocsListComponent, // this is the component I will access
BarButtonsComponent
],
imports: [
CommonModule,
DocsRouting,
// ShareModule
],
providers:[
DocsGuard,
DocsDataService // here I provide my dataService that I mentioned before
],
exports: [DocsComponent],
})
路线:
const DOCS_ROUTES:Routes = [
{path:'',redirectTo:'doclist',pathMatch:'full'},
{path:'',component:DocsComponent,children:[
{path:'doclist', component: DocsListComponent}
], canActivate:[DocsGuard] } // use `Guard` to prevent it.
];
我的dataService.ts:
private doclist:Doclist[] ; // this
getData(){
return this.doclist;
}
setData(obj){
this.doclist = obj;
}
getDocAuth(): Observable<any>{
let options = new RequestOptions({
withCredentials:true
});
// ...using get request
return this.http.get(this.docUrl,options)
// ...and calling .json() on the response to return data
.map((res:Response) =>res.json())
//...errors if any
.catch((error:any) => {
console.log(error)
})
}
Guard.ts:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>{
let subject = new Subject<boolean>();
let that = this;
this.docsDataService.getDocAuth().subscribe(
res=>{
if(res.status){
// Here I want to pass data to my component, I failed.
that.docsDataService.setData(res.data);
subject.next(true);
}else{
subject.next(false);
}
console.log("next: returning true");
},
err => {
console.log(err);
subject.next(false);
}
);
return subject.asObservable().first();
}
谢谢。
======================补充 2017-02-17 17:34============== ========
应用模块路由:
const APP_ROUTERS:Routes = [
{ path:'',component:JwLoginComponent},
{ path:'main',loadChildren:'app/main/main.module#MainModule'},
{ path:'**', component: PageNotFoundComponent }
];
主要路线:
const MAIN_ROUTES : Routes = [
{path:'main',component:MainComponent,canActivate:[DataGuard]},
{path:'share',loadChildren:'app/common/share.module#ShareModule'}
];
分享路线:
const SHARE_ROUTES:Routes = [
{path:'',redirectTo:'docs',pathMatch:'full'},
{path:'',component: ShareComponent,children:[
{ path:'docs',loadChildren:'app/docs/docs.module#DocsModule'},
// Question here: cannot get data from service set in DocsModule, but in MainModule or AppModule as providers.
{ path:'mic',loadChildren:'app/mic/mic.module#MicModule'},
{ path:'user-manage',loadChildren:'app/user-manage/user-manage.module#UserManageModule'},
{ path:'settings',loadChildren:'app/settings/settings.module#SettingsModule'},
{ path:'logs',loadChildren:'app/logs/logs.module#LogsModule'}
]},
];
我发现我在MainModule或AppModule中提供了DocService
,我可以从@mxii代码中获取数据。但是,当我将此服务设置为 DocsModule 或 ShareModule 时,我无法获取数据。
这个演示应该有帮助:
@Injectable()
export class DataService {
public data = new BehaviorSubject<any>(null);
public setData(data: any) {
this.data.next(data);
}
}
@Injectable()
export class AuthService {
public validate(user, pass): Observable<any> {
return Observable.of({ test: 'data' }).delay(123);
}
}
@Injectable()
export class DocsGuard implements CanActivate {
constructor(private _authService: AuthService, private _dataService: DataService) {}
canActivate() {
return this._authService.validate('user', 'pass').map(data => {
console.log('GUARD: auth data:', data);
// .. do something ..
if (!data || data.anyThing === 'anyValue') {
console.log('GUARD: auth WRONG');
return false; // not authenticated !
}
console.log('GUARD: auth OKAY, set data..');
this._dataService.setData(data);
return true;
})
.catch(err => {
console.log(err);
return Observable.of(false); // protect route !
});
}
}
@Component({
selector: 'my-comp',
template: `
{{ _data | async | json }}
`,
})
export class DocsListComponent {
private _data: BehaviorSubject<any>;
constructor(private _dataService: DataService) { }
ngOnInit() {
this._data = this._dataService.data;
this._data.subscribe(data => {
console.log('DocsListComponent: something changed', data);
});
}
}
现场演示:https://plnkr.co/edit/PGsTD3Ma9yDidhxEgot3?p=preview
更新
您的服务应该只包含 ONCE!!
您必须 provide
您的服务到 "highest" NgModule。
否则每个 NgModule 都会创建一个新的服务实例..
如果只有一个 NgModule provided
,它就是一个单例!
也许您必须像 RouterModule 那样创建 forRoot
和 forChild
等函数。