2016-01-21 32 views
2

我正在將一些代碼從Angular1遷移到Angular2並且出現了一些問題。我可以打開json響應,填充模板並從模板ng函數訪問數據,但無法直接從組件類訪問數據。從我閱讀的內容和看到的錯誤信息看,Angular2 http/observable似乎沒有返回純Json對象,所以我懷疑我需要重新映射它,但不知道如何。我相信也應該可以放棄使用onPromise的承諾,但還沒有設法實現這一目標。我花了很多時間搜索解決方案,並試圖實現其中的大部分,但沒有運氣。如果任何人可以建議如何重新映射可用格式的響應或直接訪問響應中的數據,將不勝感激。從服務Angular2 http observables - 如何使用undefined類型

例HTTP調用: -

getExam() { 
    return this._http.get('/json/exam.json') 
     .map(data => data.json()); 
    } 

例訂閱: -

ngOnInit() { 
     this._examsService.getExam() 
     .subscribe(response => this.exam = response); 
    console.log(this.exam.length); //this fails 
    } 

例控制檯日誌錯誤: -

TypeError: Cannot read property 'length' of undefined in [null] 

實施例的數據結構(非常簡化測試): -

{"title":"My Practice Exam", 
    "questions":[ 
    {"question":"1+1 = ", 
     "answers":[ 
     {"answer":"2","correct":"Y","selected":"N","iscorrect":""}, 
     {"answer":"5","correct":"N","selected":"N","iscorrect":""}]}, 
    {"question":"2+2 = ", 
     "answers":[ 
     {"answer":"4","correct":"Y","selected":"N","iscorrect":""}, 
     {"answer":"7","correct":"N","selected":"N","iscorrect":""}]}, 
    {"question":"3+3 = ", 
     "answers":[ 
     {"answer":"6","correct":"Y","selected":"N","iscorrect":""}, 
     {"answer":"8","correct":"N","selected":"N","iscorrect":""}]}]} 

在Angular1我能直接從功能訪問數據 - 例如如下,希望做類似的Angular2

if ($scope.myExams[0].questions[q].answers[a].correct == 'y') ... 
+0

似乎我的console.log調試沒有從ngOnInit工作,但我能夠從函數訪問完整的JSOn結構: - getTitle(){ console.log(this.exam.questions [1] .answers [ 1] .correct); } – Robert

回答

1

我認爲以下情況是正常行爲:

ngOnInit() { 
    this._examsService.getExam() 
    .subscribe(response => this.exam = response); 
    console.log(this.exam.length); //this fails 
} 

,因爲您嘗試訪問exam對象上的length屬性,該對象將稍後設置,並且響應將在此處設置(在subscribe方法中)。

也就是說,當在observable內拋出錯誤時,不會調用map運算符。如果您要變換的錯誤響應,您可以利用catch操作,如下所述:

this._examsService.getExam() 
    .subscribe(
     // Success 
     response => this.exam = response, 
     // Failure 
     response => { 
     // Do something 
     }); 

和相應的服務代碼:

getExam() { 
    return this.http.get('http://...') 
      .map(res = > res.json()) 
      .catch(res => { 
      // If you want to extract the JSON error 
      // message from the response 
      return Observable.throw(res.json()); 
      }); 
} 

否則,你也可以利用async管直接設置組件上的可觀察性而不是訂閱:

this.exam = this._examsService.getExam(); 

並在關聯的模板中

<ul> 
    <li *ngFor="#e of exam | async">{{e.name}}</li> 
</ul> 

希望它可以幫助你, 蒂埃裏

+0

謝謝,感謝回覆。它似乎確實是ngOnInit是錯誤的地方進行調試。我將調試移出到一個函數,並能夠通過點擊成功調用它,所以能夠訪問完整的JSON樹。 – Robert

+0

很高興聽到這個;-)事實上,這並沒有鏈接到組件的生命週期(ngOnInit是一個生命週期鉤子),但是對於可觀察的... –

4

有了這個代碼

ngOnInit() { 
    this._examsService.getExam() 
    .subscribe(response => this.exam = response); 
    console.log(this.exam.length); //this fails 
} 

第一線發送請求this._examsService.getExam().subscribe(...)並在響應中註冊興趣,然後console.log(this.exam.length)執行,但此時respone => this.exam = response尚未執行,因爲getExam()尚未完成連接到服務器r並收到回覆。

你需要留在事件鏈與最終返回的數據等的工作:

ngOnInit() { 
    this._examsService.getExam() 
    .subscribe(response => { 
     this.exam = response; 
     console.log(this.exam.length); //this shoudn't fail anymore 
    }); 
} 

我不知道這樣做是否解決您的問題,但你的問題沒有提供足夠的有關您的要求的更多詳細解決方案的信息。

+1

這個版本的ngOnInit沒有錯誤就完成了,但是console.log輸出只顯示「未定義」而不是返回對象的長度。 – Robert

+0

然後'getExam()'不返回一個值。你可以將'getExam()'的代碼添加到你的問題中嗎? –

+1

上面的「未定義」問題是因爲長度屬性僅存在於JSON數組上,並且在JSON對象上未定義。我能夠返回this.exam.questions.length,但this.exam.length返回「undefined」。所以......基本上這是由於我誤解了長度屬性何時可以使用。我非常感謝你的幫助,因爲它迫使我重新審視我的假設並測試更多的組合。 – Robert

相關問題