Javascript RXJS Observable 数组的简单过滤器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37991713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple filter on array of RXJS Observable
提问by Johannes
I am starting my project with Angular2 and the developers seem to recommend RXJS Observable instead of Promises.
我用 Angular2 开始我的项目,开发人员似乎推荐 RXJS Observable 而不是 Promises。
I have achieved to retrieve a list of elements (epics) from the server. But how can I filter the elments by using for example an id?
我已经实现了从服务器检索元素列表(史诗)。但是如何使用例如 id 过滤元素?
The following code is an extraction from my app and shows now the final working solution. Let's hope it helps someone.
以下代码是从我的应用程序中提取的,现在显示了最终的工作解决方案。让我们希望它可以帮助某人。
@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;
}
Thank you in advance for your help.
预先感谢您的帮助。
回答by Luka Jacobowitz
You'll want to filter the actual array and not the observable wrapped around it.
So you'll map the content of the Observable (which is an Epic[]
) to a filtered Epic
.
您需要过滤实际的数组,而不是围绕它的可观察对象。因此,您需要将 Observable 的内容(即Epic[]
)映射到已过滤的Epic
.
getEpic(id: string): Observable<Epic> {
return this.getEpics()
.map(epics => epics.filter(epic => epic.id === id)[0]);
}
Then afterwards you can subscribe
to getEpic
and do whatever you want with it.
然后之后,您可以subscribe
到getEpic
,做任何你想用它。
回答by mtpultz
You can do this using the flatMap
and filter
methods of Observable
instead of the JS array filter method in map
. Something like:
您可以使用flatMap
和filter
方法来Observable
代替 .js 中的 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!!!
flatMap
will provide singular indices for filtering and then you can get on with whatever happens next with the results.
flatMap
将提供用于过滤的单一索引,然后您可以继续处理接下来发生的结果。
If TypeScript throws a error indicating you can't compare a string and a number regardless of your use of ==
in the filter just add a +
before epic.id
in the filter, per the Angular docs:
如果 TypeScript 抛出一个错误,表明无论您==
在过滤器中使用什么,都无法比较字符串和数字,只需在过滤器中添加一个+
before epic.id
,根据 Angular 文档:
.flatMap(...)
.filter((epic) => +epic.id === id) // checks {id: 1}, then {id: 2}, etc
.subscribe(...)
Example:
例子:
https://stackblitz.com/edit/angular-9ehje5?file=src%2Fapp%2Fapp.component.ts
https://stackblitz.com/edit/angular-9ehje5?file=src%2Fapp%2Fapp.component.ts
回答by Andrei Zhytkevich
original answer with a fix:
Observables
are lazy. You have to call subscribe
to tell an observable
to send its request.
带有修复的原始答案:
Observables
懒惰。你必须打电话subscribe
告诉一个observable
发送它的请求。
getEpic(id:number) {
return this.getEpics()
.filter(epic => epic.id === id)
.subscribe(x=>...);
}
Update to Rxjs 6:
更新到 Rxjs 6:
import {filter} from 'rxjs/operators';
getEpic(id:number) {
return this.getEpics()
.pipe(filter(epic => epic.id === id))
.subscribe(x=>...);
}
回答by rinukkusu
You have to subscribe on Observable
s to get the data, since http calls are async in JavaScript.
您必须订阅Observable
s 才能获取数据,因为 http 调用在 JavaScript 中是异步的。
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);
}
);
}
You can call that method then like this:
您可以像这样调用该方法:
this.someService.getEpic(epicId, (epic: Epic) => {
// do something with it
});