RxJS订阅和局部变量为空问题

时间:2018-09-20 02:38:06

标签: angular rxjs observable

我已经在Angular应用程序中编写了此函数以调用RESTful服务,该类在Component作为服务类之外

getProducts(): IProduct[] {
    let productsObservable = this.http.get<IProduct[]>(this.productUrl).pipe(
        tap(data => console.log("All: " + JSON.stringify(data))),
        catchError(this.serviceErrorHandler)
    );

    let products: IProduct[];
    let errorMessage: string = "";

    productsObservable.subscribe(
        p => {
            products = p;
            console.log("All in subscribe: " + JSON.stringify(products));
        },
        error => errorMessage = <any>error
    );

    if (errorMessage.length > 0) {
        console.log(errorMessage);
        throw new Error(errorMessage);
    }

    console.log("All before return: " + JSON.stringify(products));
    return products;
}

我有3行代码,其中console.log用于跟踪数据。

  • tap函数中的第一个将所有JSON数据显示在控制台中,这意味着服务调用成功。
  • 我的subscribe函数中的第二个也显示JSON有效负载。
  • 但是最后一个失败了。我在列表控制台日志函数中设置了一个断点,发现变量products为空。

如果Http Observable的使用者位于同一服务类中,则结果为null。如果我将服务请求的使用者分解为Angular的组件类,则可以正常工作。是什么使Rx的Observable如此奇怪?我想我一经subscribe就会执行它。

知道我的代码有什么问题吗?

1 个答案:

答案 0 :(得分:1)

是的,这是因为传递给subscribe的函数在返回products列表之前没有被调用。

考虑一个更简单的示例:

function f() {
    let flag: boolean = false;

    setTimeout(() => flag = true, 10);

    return flag;
}

使用setTimeout,您将在JavaScript Event Loop上放置一个新任务,就像使用http.get一样。在事件循环中的任务总是在返回它们的函数之后执行。在我的示例中,无论超时时间多么短,返回值始终为false

回到您的示例,您需要从函数中返回一个Observable。无需尝试将GET调用的返回值分配给本地products变量,而是直接返回GET调用。像这样:

getProducts(): Observable<IProduct[]> {
    // your get call ...
    return productsObservable;
}

现在,这可能无法为您解决所有问题,因为您现在需要处理使用者函数中的Observable。但这或多或少是整个Observable模式的重点,它可以通知最终消费者数据更改。

在Angular中,您可以处理Observables using the async pipe