【问题标题】:Angular 2 Router Using BehaviorSubject Observable in Resolve在 Resolve 中使用 BehaviorSubject Observable 的 Angular 2 路由器
【发布时间】:2017-07-10 12:56:06
【问题描述】:

我正在尝试使用从 BehaviorSubject 返回 Observable 的 Resolve 来设置我的路由器配置。我在 angular 4.0.0-beta8 和 angular 2.4.8+router 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 确实起作用,我可能会发疯。

【问题讨论】:

  • 有什么问题? “不起作用”是没有信息的。

标签: angular angular2-routing observable angular2-observables


【解决方案1】:

好像是个bug。

在 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

【讨论】:

  • 我想我同意这应该由框架以某种方式处理,所以我很想看看关于这个 bug 的反馈是什么。
【解决方案2】:

我一夜之间想到了这一点,并意识到我使用的解析不正确。问题的症结在于路由器期望解析结果最终完成。 BehaviorSubject,即使它一次只有一个值,也永远不会完成,因为值总是可以改变的。我将this._data.asObservable() 更改为this._data.asObservable().first(),它开始工作了。现在看起来很明显!

【讨论】:

  • hmm 似乎不适用于 angular 5 ,出现白屏
【解决方案3】:

要让 Angular 6+ 在解析器中完成 observable,您需要执行以下操作:

this.myService.getData().pipe(take(1))

// or

this.myService.getData().pipe(first())

【讨论】:

  • 我无法正常工作。位于不同路径的组件没有从另一个组件获取发出的事件。我是否必须有一个解析器才能在不同路径的组件之间进行简单的数据共享?
猜你喜欢
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 2020-07-28
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
相关资源
最近更新 更多