use*_*867 4 javascript rxjs angular2-observables angular
我们要做的是从URL调用一个端点,该URL返回2个变量,这些变量可以在站点的多个部分中使用。尽管我们正在使用http调用并订阅它,但是为了加快站点速度,我们只想进行一次api调用。为此,我们在服务上创建了一个Observable。服务会在构造函数中调用一个函数,该函数设置Observable的值,但是有时在直接访问链接时会返回无法预订的undefined方法。下面是使用Microsoft ADAL库的示例代码:
首先,我们在服务中将变量设置为Observable:
@Injectable()
export class MicrosoftGraphService {
public details: Observable<any>;
Run Code Online (Sandbox Code Playgroud)
然后我们在构造函数中设置可观察值:
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();
});
});
});
Run Code Online (Sandbox Code Playgroud)
getToken函数为:
getToken(): Observable<any> {
return this._adalService
.acquireToken( this._adalService.config.endpoints.graph );
}
Run Code Online (Sandbox Code Playgroud)
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();
});
}
Run Code Online (Sandbox Code Playgroud)
然后在组件的构造函数中按如下所示调用它:
this._microsoftGraph.details.subscribe(details => {
console.log(details);
});
Run Code Online (Sandbox Code Playgroud)
这应该添加一个me端点返回的控制台日志,但是在某些页面上它会返回,而在其他页面上它会返回一个无法订阅的未定义。在两个页面的构造函数中都将正确调用MicrosoftGraphService并进行设置。
我想知道是否由于调用它的方式而发生这种情况,并且在设置它时(例如,访问基本URL会调用父组件),因为在该构造函数中调用了MicrosoftGraphService,所以它首先被初始化,因此在通过访问第二个组件时可以使用导航。但是,直接转到子组件的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
}
]
},
Run Code Online (Sandbox Code Playgroud)
问题是您public details: Observable<any>;没有在开始时初始化,并且在传递给的订阅中,每次都使用getToken()来将其设置为新的Observable
this.details = new Observable(observer => {
observer.next({
me: me
});
observer.complete();
});
Run Code Online (Sandbox Code Playgroud)
因此,您的组件在访问时将获得不同的对象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 */);
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请查看此示例