Angular2 http observables - 如何使用未定义的类型

时间:2016-01-21 14:02:49

标签: angular angular2-services

我正在将一些代码从Angular1迁移到Angular2并遇到一些问题。我可以打开json响应,填充模板,从模板ng函数访问数据,但无法直接从组件类访问数据。从我所看到的和看到的错误消息Angular2 http / observable似乎没有返回纯json对象,所以我怀疑我需要重新映射它,但不知道如何。我相信也应该可以使用onPromise回到promises,但还没有成功。我花了很多时间在Google上搜索解决方案,并试图实现大部分解决方案,但没有运气。如果有人可以建议如何将响应重新映射到可用格式或直接访问响应中的数据,那将非常感激。

来自服务的示例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') ...

2 个答案:

答案 0 :(得分: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()尚未完成连接到服务器并接收响应。

您需要留在事件链中才能使用最终返回的数据,例如:

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

我不知道这是否能解决您的问题,但您的问题并未提供有关您对更详细解决方案的要求的足够信息。

答案 1 :(得分:1)

我认为以下情况属于正常行为:

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

因为您尝试访问稍后将设置的length对象上的exam属性以及响应将在那里(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管道直接在组件上设置observable而不是订阅:

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

并在相关模板中

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

希望它可以帮到你, 亨利