RxJS 重构嵌套 map 语句
RxJS Refactor nested map statement
我有一项服务使用 @angular/http
从 API 加载数据。
我想使用此数据为我的 Components
创建检索数据的投影。
因此我写了下面的代码:
getById(id: string) {
return this.http
.get(`https://my-api.io/${id}`)
.map(response => response.json())
.map(contracts =>
contracts.map(contract => # <- Nested map
new Contract(
contract['id'],
contract['description']
)
)
);
}
在第 6th 行中,我有一个嵌套的 map
-语句,降低了代码的可读性。
问题
我可以做得更好吗? RxJS 中是否有一个运算符,我可以使用它来代替创建这种嵌套?
提前致谢!
感谢@Alexander T.. In my opinion he proposed a nice way to get around the nested map
-Statement: http://jsbin.com/hududiq/1/edit?js,console
现在我的代码如下所示:
getByAccountId(id: string) {
return this.http
.get(`http://my-api.io/${id}`)
.map(contractsData => contractsData.json())
.concatAll()
.map(contract => Observable.of(new Contract(
contract['id'],
contract['description'])))
.combineAll();
}
用这种方法做一件非常简单的事情似乎非常复杂。
如果您想不惜一切代价避免嵌套 map()
(即使这是两种完全不同的方法),您可以只使用一个 map()
,然后在数组上使用 forEach()
结果:
new Observable.of(testData)
.map(contractsData => {
var objects = [];
JSON.parse(contractsData).forEach(o => objects.push(new Contract(o['id'], o['description'])));
return objects;
})
.subscribe(val => console.log(val));
这将 return 与您的代码产生相同的结果。
查看现场演示:http://plnkr.co/edit/NQgRVSCQGgPvTkPPGz7O(我还包含了您的代码以证明结果相同)。
无论如何,我个人会使用两个 map()
,因为它更简单:
new Observable.of(testData)
.map(contractsData => JSON.parse(contractsData).map(o => new Contract(o['id'], o['description'])))
.subscribe(val => console.log(val));
顺便说一句,所有以 *all
结尾的运算符都与更高阶的 Observables(又名 Observables 发射其他 Observables)一起工作,我很惊讶你的代码能正常工作,因为你将一个普通数组传递给 .concatAll()
一个 Observable 的。它原来是 .concatAll()
的一个未记录的功能,感谢 its inner subscriber. According to the documentation 这不应该工作。
我建议使用 flatMap/selectMany 将嵌套数组展平为每个单个数组元素的新流。在下一步中,您可以使用 RxJS.map()
进行实际映射。最后将所有带有 RxJS.toArray()
的映射数组元素收集到一个提供单个数组事件的新可观察对象中:
const stream = $http('http://jsonplaceholder.typicode.com/posts')
.map(res => res.data)
.flatMap(posts => posts)
.map(post => Object.assign({}, post, { status: false }))
.toArray();
在此处查看示例:http://jsbin.com/vigizihiwu/1/edit?js,console
但我也会考虑:真的有必要这样做吗?如果您只有一个订阅者,请将接收到的数组映射到那里:
const stream = $http('http://jsonplaceholder.typicode.com/posts')
.map(res => res.data);
stream.subscribe(res => {
const posts = res.map(post => Object.assign({}, post, { status: false }));
console.log(posts);
});
我有一项服务使用 @angular/http
从 API 加载数据。
我想使用此数据为我的 Components
创建检索数据的投影。
因此我写了下面的代码:
getById(id: string) {
return this.http
.get(`https://my-api.io/${id}`)
.map(response => response.json())
.map(contracts =>
contracts.map(contract => # <- Nested map
new Contract(
contract['id'],
contract['description']
)
)
);
}
在第 6th 行中,我有一个嵌套的 map
-语句,降低了代码的可读性。
问题
我可以做得更好吗? RxJS 中是否有一个运算符,我可以使用它来代替创建这种嵌套?
提前致谢!
感谢@Alexander T.. In my opinion he proposed a nice way to get around the nested map
-Statement: http://jsbin.com/hududiq/1/edit?js,console
现在我的代码如下所示:
getByAccountId(id: string) {
return this.http
.get(`http://my-api.io/${id}`)
.map(contractsData => contractsData.json())
.concatAll()
.map(contract => Observable.of(new Contract(
contract['id'],
contract['description'])))
.combineAll();
}
用这种方法做一件非常简单的事情似乎非常复杂。
如果您想不惜一切代价避免嵌套 map()
(即使这是两种完全不同的方法),您可以只使用一个 map()
,然后在数组上使用 forEach()
结果:
new Observable.of(testData)
.map(contractsData => {
var objects = [];
JSON.parse(contractsData).forEach(o => objects.push(new Contract(o['id'], o['description'])));
return objects;
})
.subscribe(val => console.log(val));
这将 return 与您的代码产生相同的结果。
查看现场演示:http://plnkr.co/edit/NQgRVSCQGgPvTkPPGz7O(我还包含了您的代码以证明结果相同)。
无论如何,我个人会使用两个 map()
,因为它更简单:
new Observable.of(testData)
.map(contractsData => JSON.parse(contractsData).map(o => new Contract(o['id'], o['description'])))
.subscribe(val => console.log(val));
顺便说一句,所有以 *all
结尾的运算符都与更高阶的 Observables(又名 Observables 发射其他 Observables)一起工作,我很惊讶你的代码能正常工作,因为你将一个普通数组传递给 .concatAll()
一个 Observable 的。它原来是 .concatAll()
的一个未记录的功能,感谢 its inner subscriber. According to the documentation 这不应该工作。
我建议使用 flatMap/selectMany 将嵌套数组展平为每个单个数组元素的新流。在下一步中,您可以使用 RxJS.map()
进行实际映射。最后将所有带有 RxJS.toArray()
的映射数组元素收集到一个提供单个数组事件的新可观察对象中:
const stream = $http('http://jsonplaceholder.typicode.com/posts')
.map(res => res.data)
.flatMap(posts => posts)
.map(post => Object.assign({}, post, { status: false }))
.toArray();
在此处查看示例:http://jsbin.com/vigizihiwu/1/edit?js,console
但我也会考虑:真的有必要这样做吗?如果您只有一个订阅者,请将接收到的数组映射到那里:
const stream = $http('http://jsonplaceholder.typicode.com/posts')
.map(res => res.data);
stream.subscribe(res => {
const posts = res.map(post => Object.assign({}, post, { status: false }));
console.log(posts);
});