对订阅可观察对象的方法之外的数据进行角度访问

时间:2017-09-09 00:28:02

标签: javascript angular typescript observable angular-services

  

我希望能够使用.subscribe

访问我方法之外的数据

这是我的服务"工作"细

getSessionTracker(): Observable<ISessionTracker[]> {
    return this.http.get(this._url)
        .map((res: Response) => {
            let data = res.json();
            return data;
        })
       .catch(this.handleError)
} 

组件是我遇到麻烦的地方

sessionTrackers: ISessionTracker[] = [];  //  object array 

this.trackerService.getSessionTracker()
    .subscribe((sessionTrackers: ISessionTracker[]) => {
        this.sessionTrackers = sessionTrackers;
        console.log('real data in subscribe', this.sessionTrackers[0].SessionId);
    },
    (err: any) => console.log(err),
    () => console.log('getSessionTracker()'));

//在功能之外,这不起作用

 console.log('real data', this.sessionTrackers);

2个问题

  1. console.log使用.subscribe的INSIDE方法在我执行console.log时有效,但this.sessionTrackers[0].SessionId未定义,但是this.this.sessionTrackers
  2. 此数据不在方法之外工作
  3. 如何保存数据?

1 个答案:

答案 0 :(得分:5)

问题是时间问题。由于服务调用是异步的,因此在调用subscribe时数据不会立即到达。相反,当从服务返回响应时,将调用定义为subscribe方法的参数的回调函数。

这就是为什么Subscribe中的console.log工作的原因。

这是一张大致概述执行顺序的图片。

enter image description here

但是,您的代码将在确实检索时保留该值。

因此,在subscribe函数之外,您只需检查值是否存在。像这样:

if (this.sessionTrackers) { console.log(...) }

或者如果您绑定数据,则需要使用*ngIf或安全导航操作符(?)。

如果您使用的是反应形式,那么您可能需要单独设置表单模型(使用FormBuilder)并设置默认值。

我在这里有一个反应形式的例子:https://github.com/DeborahK/Angular2-ReactiveForms(查看APM文件夹)。

<强> ngOnInit

ngOnInit(): void {
    this.productForm = this.fb.group({
        productName: ['', [Validators.required,
                           Validators.minLength(3),
                           Validators.maxLength(50)]],
        productCode: ['', Validators.required],
        starRating: ['', NumberValidators.range(1, 5)],
        tags: this.fb.array([]),
        description: ''
    });

    // Read the product Id from the route parameter
    this.sub = this.route.params.subscribe(
        params => {
            let id = +params['id'];
            this.getProduct(id);
        }
    );
}

此代码设置反应形式并监视路径参数的更改。设置route参数后,调用getProduct(id)。

<强> getProduct

getProduct(id: number): void {
    this.productService.getProduct(id)
        .subscribe(
            (product: IProduct) => this.onProductRetrieved(product),
            (error: any) => this.errorMessage = <any>error
        );
}

这可以获得数据,有点类似于你正在做的事情。请注意,在订阅回调中,我调用了另一种方法:onProductRetrieved

<强> onProductRetrieved

onProductRetrieved(product: IProduct): void {
    if (this.productForm) {
        this.productForm.reset();
    }
    this.product = product;

    // Update the data on the form
    this.productForm.patchValue({
        productName: this.product.productName,
        productCode: this.product.productCode,
        starRating: this.product.starRating,
        description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
}

这是我设置反应形式的默认值的地方,因为我现在知道我拥有数据。您可以使用setValuepatchValue