2017-06-20 112 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

定義服務方法的返回類型感謝您的提示 - 我將進行此更改併發佈一個清理版本,並提供正確的用戶使用情況。 –