我已经在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
就会执行它。
知道我的代码有什么问题吗?
答案 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。