2017-06-20 133 views
0

我正在开发一个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”是我想要的数据的完整列表,但看起来订阅并不是将它们推到tradeArray中,这最终未定义。

谢谢你的时间。

+0

你可以发布你从哪个组件调用服务?顺便说一句,它是一个不好的做法,以订阅您的服务内部。您的服务只应返回观察对象 –

+0

我已更新信息。感谢用户的提示,我会研究一下。 –

+0

@ Jota.Toledo你可以在服务中绝对订阅,但仍然暴露一个可观察的,我写在这里:http://blog.jonrshar.pe/2017/Apr/09/async-angular-data.html – jonrsharpe

回答

0

所以我想你是从你的一个组件调用getTrades()。如果是这种情况,这是会发生什么:

  • 的请求将被发送
  • 请求将在后台处理异步
  • 的方法不会等待请求解决,将返回tradeArray的电流值,这是[]

为了避免这种情况,你可以让他们调用getTradeObservable()方法的订阅返回Observable重构你的组件。

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

UPDATE:假设你有贸易

如下定义
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); 
    } 
+0

谢谢。这很有帮助。然而,我注意到tradeArray似乎并没有被填充,可能暗示还有另一个问题。我尝试给任务时间来完成:'setTimeout(function(){console.log(“Test:”+ this.tradeArray);},5000);'并且即使在5秒之后数组也是未定义的。 –

+0

Trade是定义为数组还是单数元素?它只是叫我注意你试图推动服务器响应的交易者属性,这是一个数组, –

+0

贸易是一个定义的类构成tradeArray。它具有与预期的输出和服务器提供的json相同的属性 - 我打算将每个Trade从响应中单独推送到tradeArray。 –

0

谈到这部分代码:

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[]); 

    } 
} 
+0

定义服务方法的返回类型感谢您的提示 - 我将进行此更改并发布一个清理版本,并提供正确的用户使用情况。 –