我正在尝试使用Resolve设置我的路由器配置,它从BehaviorSubject返回一个Observable。我在角4.0.0-beta8和角2.4.8 +路由器3.4.8
中尝试了这个这是我的服务:
@Injectable()
export class MyService {
private _data: BehaviorSubject<Array<string>> = new BehaviorSubject(undefined);
constructor() {}
public getData(): Observable<Array<string>> {
this._data.next(['test1', 'test2', 'test3']);
let asObservable = this._data.asObservable().delay(1000);
asObservable.subscribe((myData) => {
console.log([myData, 'this console message DOES show up']);
});
// if I return here, my component's constructor and ngOnInit never fire
// return asObservable;
let fakeObservable = Observable.of(['test1', 'test2', 'test3']).delay(1000);
fakeObservable.subscribe((fakeData) => {
console.log([fakeData, 'this console message shows up']);
});
console.log([asObservable, fakeObservable]);
/* console log output
Observable {
_isScalar: false,
operator: DelayOperator,
source: Observable {
_isScalar: false,
source: BehaviorSubject {
_isScalar: false,
_value: ['test1', 'test2', 'test3'],
closed: false,
hasError: false,
isStopped: false,
observers: Array[1],
thrownError: null,
value: ['test1', 'test2', 'test3']
}
}
},
Observable {
_isScalar: false,
operator: DelayOperator,
source: ScalarObservable {
_isScalar: true,
scheduler: null,
value: ['test1', 'test2', 'test3']
}
}
*/
return fakeObservable; // this WILL reach my component constructor and ngOnInit
}
}
这是我的决心
@Injectable()
export class MyResolver implements Resolve<Array<string>> {
constructor(private myService: MyService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Array<string>>|undefined {
return this.myService.getData();
}
}
这是路由器
RouterModule.forChild([{
path: 'mypath',
component: MyComponent,
resolve: {
data: MyResolver
}
}]);
这是组件:
@Component({
selector: 'my-component',
template: '<Span>My Component</span>'
})
export class MyComponent implements OnInit {
constructor(private route: ActivatedRoute) {
console.log('component constructor');
}
ngOnInit(): void {
console.log(this.route.snapshot.data['data']); // ['test1', 'test2', 'test3']
}
}
这可能不是设计解决方案和服务之间交互的最佳方式,因此我非常愿意接受建议。但是,如果我不弄清楚为什么BehaviorSubject.asObservable()不起作用,但是模拟的observable确实有用,我可能会发疯。
答案 0 :(得分:11)
我在一夜之间想到了这一点,并意识到我正在使用解决方法。问题的关键在于路由器期望解析结果最终完成。 BehaviorSubject,即使它一次只有一个值 ,也永远不会完成,因为该值总是可以更改。我将this._data.asObservable()
更改为this._data.asObservable().first()
,然后就开始工作了。现在看来很明显了!
答案 1 :(得分:1)
好像它是一个错误。
在一个plunker中复制它:https://plnkr.co/edit/XmjC2rJ20VQWCsfncVIc?p=preview
@Injectable()
export class MyService {
private _data: BehaviorSubject<Array<string>> = new BehaviorSubject(undefined);
constructor() {
console.log('created MyService');
console.log(symbolObservable);
}
public getData(): Observable<Array<string>> {
this._data.next(['test1', 'test2', 'test3']);
this._data.do(myData => {
console.log([myData, 'this console message DOES show up']);
});
return this._data.delay(1000); // <-- won't work .. maybe an angular bug !!
return Observable.of(['test']);
}
}
在github上创建了一个错误:https://github.com/angular/angular/issues/14614
答案 2 :(得分:1)
要使Angular 6+完成解析器中的可热观测,您需要执行以下操作:
return this.myService.getData().pipe(take(1))