RxJS:带有数组的 JSON 数据,在流中进一步处理每个项目 [英] RxJS: JSON data with an array, processing each item further in the stream

查看:15
本文介绍了RxJS:带有数组的 JSON 数据,在流中进一步处理每个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到一个 HTTP 响应,如果一切顺利,其中包含一个编码为 JSON 的数组.
我想获取这个数组,过滤掉一些项目,并将传递的项目作为事件处理.

I receive a HTTP response, which contains, if all goes well, a single array, coded as JSON.
I want to get this array, filter out some items, and process the passing items as events.

我目前所做的是:

    return this._http.get(url)
        .map((res:Response) => res.json())
        .map((data:any) => {
            if (!Array.isArray(data) || data.length == 0) {
                throw new Error("No items returned, URL: " + url);
            }
            let projects = <ProjectModel[]>service.fromJSONarray(data, this._http);
            return Observable.from(projects)
                .filter((project: ProjectModel) => project.parentProject == null)
                .subscribe(project -> ...)
        })

但是我不喜欢嵌套.我认为有一种方法可以做到这一点:

However I don't like the nesting. I assume there's a way to do this:

    return this._http.get(url)
        .map((res:Response) => res.json())
        .map((data:any) => {
            ...
            let projects = <ProjectModel[]>service.fromJSONarray(data, this._http);
            ???
        })
        .filter((project: ProjectModel) => project.parentProject == null)
        .subscribe(project -> ...)

如何实现?

推荐答案

假设您使用的是 RxJS 5,使用 concatAll() 及其未记录的用于展平嵌套数组的功能会更简单,即使 concatAll() 用于处理高阶 Observable.

Assuming you're using RxJS 5 there's even easier way with concatAll() and its undocumented feature for flattening nested arrays even though concatAll() is made to work with Higher-Order Observables.

let data = '[{"id":1},{"id":2},{"id":3},{"id":4}]';

Observable.of(data)
    .map(JSON.parse)
    .concatAll() // each object is emitted separately
    .map(p => p) // transform to ProjectModel
    .filter(p => true) // filter whatever you want
    .subscribe(v => console.log(v));

如果 service.fromJSONarray 只返回 ProjectModel 的一个实例,它可以是这么简单.如果您需要 service.fromJSONarray 返回一个数组,您可以将它放在 map(JSON.parse)concatAll() 之间.此演示打印到控制台:

If service.fromJSONarray returns just a single instance of ProjectModel it can be this simple. If you need service.fromJSONarray to return an array you'd put it between map(JSON.parse) and concatAll(). This demo prints to console:

{ id: 1 }
{ id: 2 }
{ id: 3 }
{ id: 4 }

但是,如果您从 service.fromJSONarray 返回一个 Observable,该 Observable 会发出其他 observable,因为它需要执行一些额外的 HTTP 请求,您需要使用 concatMap()flatMap() 取决于您是否要保持相同的项目顺序:

However, if you were returning an Observable from service.fromJSONarray that emits other observables because it needs to do some extra HTTP requests you'd need to use concatMap() or flatMap() depending on whether you want to keep the same order of items or not:

let data = '[{"id":1},{"id":2},{"id":3},{"id":4}]';

function fromJSONarray(arr) {
    return Observable.from(arr)
        .flatMap(p => Observable.of(p));
}

Observable.of(data)
    .map(d => fromJSONarray(JSON.parse(d)))
    .concatAll()
    .map(p => p) // transform to ProjectModel
    .subscribe(v => console.log(v));

结果是一样的.

类似问题:

使用 Observable 合并子数组

RxJS 重构嵌套映射语句

这篇关于RxJS:带有数组的 JSON 数据,在流中进一步处理每个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆