订阅可观察对象返回未定义
Posted
技术标签:
【中文标题】订阅可观察对象返回未定义【英文标题】:Subscribe to observable is returning undefined 【发布时间】:2018-03-27 21:35:22 【问题描述】:所以我正在尝试订阅一个从本地 JSON 文件返回数据的简单服务。
我已经设法让服务正常工作,我可以在函数中将其注销,但是当我在 angular 2 组件中订阅服务时,它总是未定义。我不确定为什么?任何帮助将不胜感激。
API 服务
export class ApiService
public data: any;
constructor(private _http: Http)
getData(): any
return this._http.get('api.json').map((response: Response) =>
console.log('in response', response.json()); //This logs the Object
this.data = response.json();
return this.data;
)
.catch(this.handleError);
组件
export class AppComponent
public data: any
public informationData;
constructor(private _api: ApiService)
public ngOnInit(): void
console.log(this.getDataFromService()); // This return undefined
public getDataFromService()
this._api.getData().subscribe(response =>
this.informationData = response;
return this.informationData;
);
【问题讨论】:
getDataFromService
本身不返回任何内容。将 .subscribe
更改为 .map
并返回结果 observable,然后在模板中使用 | async
解决它。
订阅函数不返回数据。它返回一个Subscription
对象。即,如果您返回函数调用本身。
@SurajRao 是的,我注意到了,如何让它返回响应数据?
你想把它退回到哪里?
如果你想要的话,你可以将它保存在订阅中的类变量中
【参考方案1】:
也许一些图片有帮助?
这里的数字表示操作的顺序。
发送 Http 请求
-
组件被初始化并调用movieService的getMovies方法。
movieService getMovies 方法返回一个 Observable。不是此时的数据。
组件在返回的 Observable 上调用
subscribe
。
get
请求被提交到服务器进行处理。
ngOnInit
方法已完成。
subscribe
之后的任何代码都无法访问movies
属性,因为尚未返回数据。
接收 Http 响应
在稍后的某个时间点......
-
电影返回到服务。
如果处理成功,则执行第一个回调函数。
本地电影属性分配给从服务返回的电影。仅在此处最终设置了 movies 属性。
在第 8 步之前尝试访问 movies 属性会导致错误。
我们可以在这里访问值吗?没有
修复它:
【讨论】:
经过几天的搜索,我找到了您的帖子。非常感谢你的黛博拉!这就是我要找的。但是你能告诉我如何解析/处理来自 this.movies 的数据吗?我需要收集它并使用 chart.js/ng 图表显示在图表中 这写得非常好,演示得非常好。谢谢@DeborahK! 这似乎没有奏效。调用 this.movies.length,仍然没有填充我的 html:m.name 导致 列表li> 没有名字。即使添加 m.name|async 也没有用。 这不是这个例子的重点。调用this.movies.length
不会导致列表填充。调用.subscribe
并设置this.movies = movies
会导致this.movies
填充。这篇文章试图说明为什么你不能得到 observable 之外的长度。尝试发布一个新问题并显示您的一些代码。标记我,我去看看。
多么奇妙的解释!任何与异步作斗争的人都应该看看这个回复。【参考方案2】:
objResponse;
this.service.getData().subscribe((result: any)=>
this.objResponse=result;
不需要退货
【讨论】:
【参考方案3】:你可以这样做:
在您的应用组件中:
public getDataFromService()
this._api.getData(this);
public setData(data: any)
this.data=data;
在您的服务/api.ts 中:
public getData(obj: appComponentModel)
this.http.get(url).subscribe(res => obj.setData(res));
【讨论】:
【参考方案4】:尝试:
getData(): any
return this._http.get('api.json');
或
getData(): any
return this._http.get('api.json').map((response: Response) =>
response.json();
)
【讨论】:
【参考方案5】:您在同步和异步功能之间遇到了问题。你的问题是:getDateFromService
是同步的,里面的内容是异步的。因此,当ngOnInit
函数调用getDataFromService
时,您的代码不会等待异步任务。你getDataFromService
需要返回一个观察者或者需要实现你的API的返回(你需要选择)。
public ngOnInit(): void
console.log(this.getDataFromService().subscribe(data => console.log(data)); // This return undefined
public getDataFromService()
return this._api.getData();
【讨论】:
这很好用,但是当我尝试将data
添加到类变量时它仍然返回 undefined
你想从哪里得到你的api的响应?因为您的问题是您使用同步/异步功能。如果您的班级中有undefined
,则可能是您的班级在执行console.log
之前没有等待异步调用响应【参考方案6】:
而不是像你那样在 ngOnInit() 方法中记录
public ngOnInit(): void
console.log(this.getDataFromService()); // This return undefined
在 subscribe() 方法中记录为
export class AppComponent
public data: any
public informationData;
constructor(private _api: ApiService)
public ngOnInit(): void
this.getDataFromService(); //don't log here, logging here will return undefined
public getDataFromService()
this._api.getData().subscribe(response =>
this.informationData = response;
console.log(this.informationData); //log here, like this
return this.informationData;
);
【讨论】:
【参考方案7】:将“订阅”想象成一个单独的线程运行,在“订阅”内部的匿名函数中编写所需的所有内容。只要“数据”可用,它就会在 subscribe 方法中可用。
希望这会有所帮助。
【讨论】:
以上是关于订阅可观察对象返回未定义的主要内容,如果未能解决你的问题,请参考以下文章
订阅字段必须返回 Async Iterable。收到:未定义