2

我正在将一些代码从 Angular1 迁移到 Angular2 并遇到一些问题。我可以打开 json 响应、填充模板并从模板 ng 函数访问数据,但无法直接从组件类访问数据。从我读过的内容和看到的错误消息来看,Angular2 http / observable 似乎没有返回纯 json 对象,所以我怀疑我需要重新映射它,但不确定如何。我相信也应该可以使用 onPromise 退回到承诺,但还没有设法让它发挥作用。我花了很多时间在谷歌上搜索解决方案,并尝试实施其中的大部分,但没有运气。如果有人可以建议如何将响应重新映射为可用格式或直接访问响应中的数据,将不胜感激。

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

2 回答 2

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
    });
}

我不知道这是否能解决您的问题,但您的问题没有提供足够的信息来说明您对更详尽的解决方案的要求。

于 2016-01-21T14:11:35.737 回答
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管道直接在组件上设置可观察对象而不进行订阅:

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

并在相关的模板中

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

希望它可以帮助你,蒂埃里

于 2016-01-21T14:09:48.353 回答