【问题标题】:Using Angular Observers to fetch data over a network使用 Angular Observers 通过网络获取数据
【发布时间】:2017-06-20 21:26:52
【问题描述】:

我正在开发一个 Angular 应用程序,其中包含用户可以添加的(金融)交易列表。这一直进展顺利,我正在尝试从服务提供的静态列表切换到尝试从本地 Node.js 服务器获取数据。我正在使用观察者来异步获取交易列表。

我一直在关注 Angular 的 HTTP tutorial 和相关的 plunker。但是,即使我可以看到来自服务器的数据,我也无法使用 .subscribe() 方法从中获取一组有用的数据。

这是我连接到节点服务器的服务:

   @Injectable()
export class TradeService {
  private url = '...';  // URL to web API
  tradeArray: Trade[] = [];
  constructor(private http: Http) { }
  //-----------GETTERS---------------//
  getTradeObservable(): Observable<Trade> {
    return this.http.get(this.url)
      .map(this.extractData)
      .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    console.log("body:" + body);
    console.log("Entire Body.trades: " + body.trades);
    return body.trades;
  }

  getTrades(): any {
    this.getTradeObservable()
      .subscribe(
          trade => this.tradeArray.push(trade));
    return this.tradeArray;
  }

以下是节点服务器本身的相关部分:

var TRADES = { "trades": [
   {"id": 0, "cust": "Ben", "hasSub": true,
       "subcust": "Rigby", "type": "s", "security": "001", "ticket": "99"},
   ...
   {"id": 9, "cust": "Uber Bank", "hasSub": true,
            "subcust": "Lil Bank", "type": "p", "security": "456", "ticket": "56"}
]};


////////////Get Requests/////////////////

//this route returns all data in JSON format
app.get('/', function(req, res) {
    res.send(JSON.stringify(TRADES));
    });

getTrades 的预期输出:

[
   {id: 0, cust: "Ben", hasSub: true,
       subCust: "Rigby", type: "s", security: '001', ticket: '99'},
   ...
   {id: 9, cust: "Uber Bank", hasSub: true,
            subCust: "Lil' Bank", type: "p", security: '456', ticket: '56'},
];

以及服务注入和调用的地方之一:

export class SubmittedComponent {
  constructor(private tradeService: TradeService) { }

  //initally show all trades
  rows = this.tradeService.getTrades();
...

我可以在浏览器控制台中看到“整个 body.trades”是我想要的数据的完整列表,但似乎 subscribe 没有将它们推送到 tradeArray,最终未定义。

感谢您的宝贵时间。

【问题讨论】:

  • 您能发布调用服务的组件吗?顺便说一句,在您的服务内部订阅是一种不好的做法。你的服务应该只返回 observables
  • 我已经更新了帖子。感谢订阅者的提示,我会调查的。
  • @Jota.Toledo 您绝对可以在服务内订阅,但仍然公开一个可观察对象,我在这里写过:blog.jonrshar.pe/2017/Apr/09/async-angular-data.html
  • 是的,但在这种情况下,您使用的是主题,这是另一个主题。不错的文章,也许可以帮助 OP

标签: json angular rxjs angular2-http


【解决方案1】:

所以我想你是从你的一个组件调用 getTrades() 。如果是这样的话,将会发生这样的事情:

  • 请求将被发送
  • 请求将在后台异步处理
  • 该方法不会等待请求被解析,而是返回tradeArray的当前值,即[]

为避免这种情况,您可以重构组件,以便它们调用 getTradeObservable() 方法并订阅返回的 Observable

更新:另一种选择是重构您的服务以使用 Subject', and expose it to your components through anObservable`。

更新:假设您有以下贸易定义

export interface Trade{
   id: number;
   cust: string;
   hasSub: boolean;
   subCust: string;
   type: string;s
   security: string;
   ticket: string;
}

你可以试试下面的方法

class TestComponent {
  data: Trade[];
  // inject service in component

  getData(){
     this.service.getTradesObservable().subscribe(data => this.data = data);
  }
}

并将 getTradesObservable 的定义更改为:

getTradeObservable(): Observable<Trade[]> {
    return this.http.get(this.url)
      .map(this.extractData)
      .catch(this.handleError);
  }

【讨论】:

  • 谢谢。这很有帮助。但是,我注意到 tradeArray 似乎从未填充过,这可能表明存在另一个问题。我尝试给任务时间来完成:setTimeout(function() {console.log("Test:" + this.tradeArray);}, 5000);,即使在 5 秒后数组未定义。
  • Trade 是定义为数组还是单个元素?它只是引起了我的注意,您尝试推送服务器响应的交易者属性,这是一个数组,
  • Trade 是组成 tradeArray 的已定义类。它具有与预期输出和服务器提供的 json 相同的属性——我打算将每个 Trade 从响应单独推送到 tradeArray。
  • 就是这样。谢谢您的帮助。纠正不良做法后,我将在帖子中添加清理后的版本。
  • 另一个提示:: http 请求总是会返回 POJO。您只能通过调用类的构造方法将它们映射到类。因此,最好只通过接口定义服务方法的返回类型
【解决方案2】:

只说这部分代码:

getTrades(): any {
    this.getTradeObservable()
      .subscribe(
          trade => this.tradeArray.push(trade));
    return this.tradeArray;
  }

由于getTradeObservable 是异步的,这一行:return this.tradeArray; 将(可能)在可观察对象被解析之前执行,您应该从您的服务中删除getTrades 方法,而是获取getTradeObservable 返回的可观察对象您的组件,而不是期望整个事物返回您想要的值,您应该像这样在订阅中分配该值:

    @Component({
       providers:[TradeService ]
    })
    export class myComponent{
        trades:Trade[];
    constructor(tradeService:TradeService){
        tradeService.getTradeObservable().subscribe(tradeRes=>this.trades=tradeRes as Trade[]);

    }
}

【讨论】:

  • 感谢您的提示 -- 我将进行此更改并发布一个具有正确订阅者使用情况的清理版本。
猜你喜欢
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2018-05-29
  • 2020-03-07
  • 2016-12-13
  • 2019-03-07
  • 1970-01-01
  • 2013-07-01
相关资源
最近更新 更多