尝试在 Angular 2 中循环可观察对象时出错

Posted

技术标签:

【中文标题】尝试在 Angular 2 中循环可观察对象时出错【英文标题】:Error trying to loop Observable Object in Angular 2 【发布时间】:2017-05-17 01:06:18 【问题描述】:

我被困在这里,试图在我的用户服务上循环可观察对象。 Chrome 的控制台抛出:

error_handler.js:47 例外:未定义不是函数

这是我的代码:

users.component.ts

import  Component, OnInit  from '@angular/core';
import  UserService  from '../user.service';
import  Observable  from 'rxjs/Rx';
import  User  from '../user';

@Component(
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css']
)
export class UsersComponent implements OnInit 

 people: Observable<User[]>;
  constructor( private _userService: UserService)  

  ngOnInit() 
        this.people = this._userService.getAll();
        console.log(this.people);
    

users.service.ts

import  Injectable  from '@angular/core';
import  Http, Response, Headers  from '@angular/http';
import  Observable  from 'rxjs/Rx';
import  ErrorObservable  from 'rxjs/observable/ErrorObservable';
import  User  from './user';


@Injectable()
export class UserService 

  private baseurl: string= 'http://swapi.co/api';

  constructor(private http: Http)  
      console.log("User service initialized");
  


  getAll(): Observable<User[]>
    let users$ = this.http
      .get(`$this.baseurl/people`,headers: this.getHeaders())
      .map(this.mapUsers);

      return users$;
  


  private getHeaders()
    let headers = new Headers();
    headers.append('Accept', 'application/json');
    return headers;
  


  mapUsers(response: Response): User[]
       return response.json().results.map(this.toUser);
  


  toUser(r:any): User
    let user = <User>(
        id: this.extractId(r),
        name: r.name
    );
    console.log('Parsed user'+user.name);
    return user;
  


extractId(personData:any)
    let extractedId = personData.url.replace('http://swapi.co/api/people/','').replace('/','');
    return parseInt(extractedId);



users.component.html

<ul class="people">
    <li *ngFor="let person of people | async " >
        <a href="#">
          person.name
        </a>
    </li>
</ul>

user.ts

export interface User
    id: number;
    name: string;

当我从模板中删除 HTML 代码时,一切正常(控制台上没有错误)所以,我猜 'people' 对象有问题,显然我无法迭代响应。请大家帮忙,这里将不胜感激。

【问题讨论】:

【参考方案1】:

最可能的原因是您处理map 回调的方式

getAll(): Observable<User[]>
  let users$ = this.http
    .get(`$this.baseurl/people`,headers: this.getHeaders())
    .map(this.mapUsers);


mapUsers(response: Response): User[]
  return response.json().results.map(this.toUser);


toUser() 

在回调函数中使用this 时需要小心。上下文有时会让你感到困惑。在这种情况下,.map(this.toUser) 中的 this 不指向类实例。你需要绑定它,即

  let users$ = this.http
    .get(`$this.baseurl/people`,headers: this.getHeaders())
    .map(this.mapUsers.bind(this));

当您使用 bind(this) 时,您是说在 mapUsers 函数内对 this 的任何使用都应绑定到类实例。

当你使用箭头函数时,你不必担心这种区别,因为它保留了词法范围上下文

let users$ = this.http
  .get(`$this.baseurl/people`,headers: this.getHeaders())
  .map(res => response.json().results.map(this.toUser));

此外,即使传递toUser 函数也存在与您使用this.extractId(r) 相同的问题。你还需要绑定那个

mapUsers(response: Response): User[]
  return response.json().results.map(this.toUser.bind(this));

【讨论】:

感谢 pesskillet 的回复。很高兴知道..我会记住的。我修改了函数,更新了地图调用: .map(this.mapUsers.bind(this)); ...但现在控制台抛出:未捕获的错误:模块构建失败:错误:/home/webdeveloper/Workspace/Angular2/unibague_directory_v2/src/app/user.service.ts (26,14): Type 'Observable' 不可分配给类型 'Observable'。类型“”不可分配给类型“User[]”。 如果我使用第二个选项 (res =>),我的代码编辑器 (Visual Studio) 会在“响应”字样下划线。 (变量未声明) 嗯,是的,这是一个错字。应该是response,而不是res 嘿,peeskillet,非常感谢你..它现在可以工作了。你让我开心。

以上是关于尝试在 Angular 2 中循环可观察对象时出错的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6:尝试区分“[object Object]”时出错。只允许使用数组和可迭代对象

Angular 2:可观察订阅未正确读取数据[重复]

Angular:尝试与'[object Object]'进行比较时出错。仅允许数组和可迭代的对象

如何在 Angular Controller 中观察可变参数

Angular/RxJS:带有可观察对象的嵌套服务调用

将可观察对象的一部分作为角度分量的输入时出错?