在 RxJS pipable 运算符之间传递数据的最佳方式?
Best way to pass data between RxJS pipable operators?
除了在 RxJS 的下一个 pipable 运算符中获取其响应数据外,我还想传递 URL。您认为实现这一目标最明智的方法是什么?
提前致谢。
这是一个例子。
https://stackblitz.com/edit/angular-rxjs-passing-data-to-next-operator-question
我尝试了一些运算符,但找不到合适的。
(实际上,我什至不知道为什么将 returns 可观察到的函数传递给 mergeMap
会导致在下一个运算符中将数据作为函数的参数...)
from([
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
])
.pipe(
mergeMap(url => this.getData(url)),
tap(posts => console.log(posts[0])), // I want to get url too here!!
).subscribe();
我希望在 pipable 运算符中得到 url 及其响应数据。
您可以将响应映射到您想要的任何内容:
from([
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
]).pipe(
mergeMap(url => this.getData(url).pipe(
map(response => ({ response, url })),
)),
tap(response => console.log(response)),
).subscribe();
查看mergeMapmergeMap(project: function: Observable, resultSelector: function: any, concurrent: number): Observable
的签名,可以使用resultSelector
参数:
from([
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
])
.pipe(
mergeMap(url =>
this.getData(url),
(outerValue, innerValue) => ({ url: outerValue, posts: innerValue })),
tap(({ posts, url })=> {
console.log(posts);
console.log(url);
})
).subscribe();
这将有效地将 url
和 this.getData(url)
的结果映射到可在 tap()
中使用的对象。
这是您的 example 修改后的实际效果。
注意: 结果选择器在 process of being deprecated/removed 中。虽然此解决方案目前可能有效,但在未来的 RxJS 版本中将不再可行 (7.x)。 @martin提供的答案肯定更"future-proof".
希望对您有所帮助!
Martin 的答案对于给定的代码示例是正确的。
然而,对于更复杂和更长的运算符链,将先前的值传递给后续运算符可能会成为一项相当复杂的任务。尤其是在使用扩展运算符等更高级的运算符时。
在那些情况下,我更喜欢使用闭包来存储这些值:
const myStream$ = () => {
const urls = [
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
];
let dataUrl;
return from(urls).pipe(
mergeMap(url => {
dataUrl = url;
return this.getData(url)
}),
// ... assuming more operators are called here ... //
tap(posts => console.log(posts[0], dataUrl))
);
};
myStream$().subscribe();
但同样,对于更简单的运算符链,向返回的对象添加值是可行的方法。
除了在 RxJS 的下一个 pipable 运算符中获取其响应数据外,我还想传递 URL。您认为实现这一目标最明智的方法是什么? 提前致谢。
这是一个例子。 https://stackblitz.com/edit/angular-rxjs-passing-data-to-next-operator-question
我尝试了一些运算符,但找不到合适的。
(实际上,我什至不知道为什么将 returns 可观察到的函数传递给 mergeMap
会导致在下一个运算符中将数据作为函数的参数...)
from([
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
])
.pipe(
mergeMap(url => this.getData(url)),
tap(posts => console.log(posts[0])), // I want to get url too here!!
).subscribe();
我希望在 pipable 运算符中得到 url 及其响应数据。
您可以将响应映射到您想要的任何内容:
from([
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
]).pipe(
mergeMap(url => this.getData(url).pipe(
map(response => ({ response, url })),
)),
tap(response => console.log(response)),
).subscribe();
查看mergeMapmergeMap(project: function: Observable, resultSelector: function: any, concurrent: number): Observable
的签名,可以使用resultSelector
参数:
from([
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
])
.pipe(
mergeMap(url =>
this.getData(url),
(outerValue, innerValue) => ({ url: outerValue, posts: innerValue })),
tap(({ posts, url })=> {
console.log(posts);
console.log(url);
})
).subscribe();
这将有效地将 url
和 this.getData(url)
的结果映射到可在 tap()
中使用的对象。
这是您的 example 修改后的实际效果。
注意: 结果选择器在 process of being deprecated/removed 中。虽然此解决方案目前可能有效,但在未来的 RxJS 版本中将不再可行 (7.x)。 @martin提供的答案肯定更"future-proof".
希望对您有所帮助!
Martin 的答案对于给定的代码示例是正确的。
然而,对于更复杂和更长的运算符链,将先前的值传递给后续运算符可能会成为一项相当复杂的任务。尤其是在使用扩展运算符等更高级的运算符时。
在那些情况下,我更喜欢使用闭包来存储这些值:
const myStream$ = () => {
const urls = [
'https://jsonplaceholder.typicode.com/posts',
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/albums',
];
let dataUrl;
return from(urls).pipe(
mergeMap(url => {
dataUrl = url;
return this.getData(url)
}),
// ... assuming more operators are called here ... //
tap(posts => console.log(posts[0], dataUrl))
);
};
myStream$().subscribe();
但同样,对于更简单的运算符链,向返回的对象添加值是可行的方法。