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

查看:288
本文介绍了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.

到目前为止,我所做的是:

What I do so far is:

    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()可用于高阶可观察量。

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 }

但是,如果你从一个Observable返回 service.fromJSONarray 发出其他可观察对象,因为它需要做一些你需要使用的额外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));

结果相同。

类似的问题:

使用Observables合并子阵列

RxJS Refactor嵌套地图声明

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

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