对RXJS Observable数组进行简单过滤

时间:2016-06-23 12:32:04

标签: javascript typescript angular rxjs observable

我正在使用Angular2开始我的项目,开发人员似乎推荐RXJS Observable而不是Promises。

我已经实现从服务器检索元素列表(史诗)。 但是如何通过使用例如id来过滤元素?

以下代码是从我的应用程序中提取的,现在显示最终的工作解决方案。我们希望它可以帮到某人。

@Injectable()
export class EpicService {

  private url = CONFIG.SERVER + '/app/';  // URL to web API

  constructor(private http:Http) {}

  private extractData(res:Response) {
    let body = res.json();
    return body;
  }

  getEpics():Observable<Epic[]> {
    return this.http.get(this.url + "getEpics")
      .map(this.extractData)
      .catch(this.handleError);
  }

  getEpic(id:string): Observable<Epic> {
    return this.getEpics()
      .map(epics => epics.filter(epic => epic.id === id)[0]);
  }
}

export class EpicComponent {

  errorMessage:string;
  epics:Epic[];
  epic:Epic;

  constructor(
    private requirementService:EpicService) {
  }

  getEpics() {
    this.requirementService.getEpics()
      .subscribe(
        epics => this.epics = epics,
        error => this.errorMessage = <any>error);
  }

  // actually this should be eventually in another component
  getEpic(id:string) {
    this.requirementService.getEpic(id)
        .subscribe(
        epic => this.epic = epic,
        error => this.errorMessage = <any>error);
  }
}

export class Epic {
  id: string;
  name: string;
}

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:58)

您需要过滤实际数组,而不是过滤掉它周围的observable。 因此,您可以将Observable的内容(Epic[])映射到已过滤的Epic

getEpic(id: string): Observable<Epic> {
  return this.getEpics()
     .map(epics => epics.filter(epic => epic.id === id)[0]);
}

然后你可以subscribegetEpic并随意做任何事情。

答案 1 :(得分:26)

您可以使用flatMap的{​​{1}}和filter方法代替Observable中的JS数组过滤方法来执行此操作。类似的东西:

map

this.getEpics() .flatMap((data) => data.epics) // [{id: 1}, {id: 4}, {id: 3}, ..., {id: N}] .filter((epic) => epic.id === id) // checks {id: 1}, then {id: 2}, etc .subscribe((result) => ...); // do something epic!!! 将提供用于过滤的单数索引,然后您可以继续使用结果接下来发生的任何事情。

如果TypeScript抛出错误,指示您无法比较字符串和数字,无论您在过滤器中使用flatMap,只需在过滤器中==之前添加+,根据Angular文档:

epic.id

示例:

https://stackblitz.com/edit/angular-9ehje5?file=src%2Fapp%2Fapp.component.ts

答案 2 :(得分:1)

带有修复的原始答案: Observables很懒惰。您必须致电subscribe告诉observable发送请求。

  getEpic(id:number) {
    return this.getEpics()
           .filter(epic => epic.id === id)
           .subscribe(x=>...);
  }

更新到Rxjs 6:

import {filter} from 'rxjs/operators';

getEpic(id:number) {
        return this.getEpics()
               .pipe(filter(epic => epic.id === id))
               .subscribe(x=>...);
      }

答案 3 :(得分:0)

您必须在newUser.Roles.Add(new IdentityUserRole {UserId = newUser.Id, RoleId = "your role id"}); 订阅才能获取数据,因为http调用在JavaScript中是异步的。

Observable

您可以像这样调用该方法:

getEpic(id: number, callback: (epic: Epic) => void) {
    this.getEpics().subscribe(
        epics: Array<Epic> => {
            let epic: Epic = epics.filter(epic => epic.id === id)[0];
            callback(epic);
        }
    );
}