订阅可观察对象返回未定义

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 上调用 subscribeget 请求被提交到服务器进行处理。 ngOnInit 方法已完成。

subscribe 之后的任何代码都无法访问movies 属性,因为尚未返回数据。

接收 Http 响应

在稍后的某个时间点......

    电影返回到服务。 如果处理成功,则执行第一个回调函数。 本地电影属性分配给从服务返回的电影。仅在此处最终设置了 movies 属性。

在第 8 步之前尝试访问 movies 属性会导致错误。

我们可以在这里访问值吗?没有

修复它:

【讨论】:

经过几天的搜索,我找到了您的帖子。非常感谢你的黛博拉!这就是我要找的。但是你能告诉我如何解析/处理来自 this.movi​​es 的数据吗?我需要收集它并使用 chart.js/ng 图表显示在图表中 这写得非常好,演示得非常好。谢谢@DeborahK! 这似乎没有奏效。调用 this.movi​​es.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。收到:未定义

未调用 RxSwift 订阅块

TypeError:myObservableArray未定义

观察者模式和发布订阅模式(上)

Angular2 Observables - 创建我自己的 - 订阅者未定义