我在使用rxjs 6.5的Typescript / Angular中有这种情况:
main(){
const properties = ['session', 'user'];
const source: Observable<any> = from(properties);
source
.pipe(
mergeMap(key => this.getKey().map((value) => ({key: key, value: value}))),
tap((result) => {
// sending the result elsewhere;
}),
).subscribe(
(result) => {
console.log('Final result ->', result);
}
);
console.log('\n');
}
getKey(): Observable<any> {
// Mock function that returns an observable that emits 1 value
const observable = from(['test']);
return observable;
}
输出为:
Final result -> {key: "session", value: "test"}
Final result -> {key: "user", value: "test"}
第一个问题: 我如何以最优雅的方式以原始订阅的价格返回1个值,并结合内部可观测值的结果?
我想要的输出以及这种订阅方式(因为我希望此合并操作在管道中)将是:
(...).subscribe(
(result) => {console.log('Final Result:', result}
)
OUTPUT:
Final result -> [{key: "session", value: "test"}, {key: "user", value: "test"}]
第二个问题 如果我不关心内部可观测值的结果,如何只返回1值或如何知道所有内部可观测值何时完成?
谢谢。
答案 0 :(得分:0)
第一个问题,您可以使用scan
来处理和累积输出
mergeMap(key => from(this.getKey())),
scan((acc,curr) =>acc.concat([{key: curr.key, value: curr.value}]),[])),
2n个问题
使用first()
运算符仅从内部可观察到的一个输出
将finalize()
附加到内部可观察对象,当内部可观察对象完成时会触发。或使用last()
来获取最后的累积结果
mergeMap(key => from(this.getKey())),
scan((acc,curr) =>acc.concat([{key: curr.key, value: curr.value}]),[])),
first()
答案 1 :(得分:0)
使用减少
.pipe(
reduce((results, result) => {
results.push(result);
return results;
}, [])
)
只有其他所有对象都发出后,结果的Observable才会发出,并且发出的值将是所有结果的数组。
答案 2 :(得分:0)
这是一个带注释的示例,可以帮助您澄清有关您所询问的订阅过程的问题。
第一季度:
正如另一个答案所指出的,reduce
运算符是您想要包含在source
管道中的内容。 reduce
的一个关键细节是它仅在完成可观察到的相应源时发出。相反,如果您希望在内部可观测量完成时发射,则scan
是合适的。与后者的另一个区别是,它不需要源代码完成。
第二季度:
关于这个问题,请参考下面的示例,并将处理管道的每个参数都视为单个请求的生存期。在此,完成是隐式的。它在处理内部可观测值的最后一个值之后发生。
但是,如果内部可观对象没有界限,那么就不可能知道所有内部可观对象何时完成。在这种情况下,您会发现reduce()
不起作用。
const { from, of, Subject } = rxjs;
const { mergeMap, map, tap, reduce, scan } = rxjs.operators;
// Use a subject to simulate processing.
// Think of each argument as a request to the processing pipeline below.
const properties = new Subject();
// Establish processing pipeline
const source = properties.pipe(
// `mergeMap` here flattens the output value to the combined inner output values
mergeMap(props =>
// Each item inside the argument should be piped as separate values
from(props).pipe(
// `mergeMap` here flattens the output value to `{ key, value }`
mergeMap(key =>
of('test').pipe(
map(value => ({ key, value })),
),
),
// Unlike `scan`, `reduce` only emits upon "completion".
// Here, "completion" is implicit - it is after the last
// element of `from(props)` has been processed.
reduce((a, i) => [...a, i], []),
)
),
);
// Subscribe to the pipeline to observe processing.
source.subscribe(console.log);
// Trigger a processing request with an argument
properties.next(['session', 'user']);
// Trigger another processing request
properties.next(['session', 'user']);
<script src="https://unpkg.com/rxjs@6.5.1/bundles/rxjs.umd.min.js"></script>
答案 3 :(得分:0)
Q1::您需要一个 toArray
—它将所有流值组合到一个数组中:
第二季度::要忽略流中的所有值,并在完成时发出一个值
concat(
source$.pipe(ignoreElements()),
of(true)
)
请参见"Emit a value upon source completion"在操场上的示例
答案 4 :(得分:0)
要获得mergeMap的所有响应的合并结果,您还可以尝试如下操作:
return this.request1().pipe(
mergeMap(res1=> this.request2(res1.id).pipe(
map(res2=> {
return {
res1: res1,
res2: res2
}
})
))
)