Angular 6:将 Observable 响应传递给另一个 Observable
Posted
技术标签:
【中文标题】Angular 6:将 Observable 响应传递给另一个 Observable【英文标题】:Angular 6: Passing Observable response to another Observable 【发布时间】:2019-01-07 04:07:32 【问题描述】:我在使用 angular typescript 中的 observable 获取 Web API 输出时遇到问题。
我想获取第一个 observable 返回的值,然后将其值传递给另一个 observable。到目前为止,这就是我所写的。
let output: any;
let output2: any;
_httpClient.get('http://localhost:5000/api/mycontroller')
.subscribe((output_1) =>
output = output_1;
);
alert(output);
_httpClient.get('http://localhost:5000/api/mycontroller2'+output)
.subscribe((output_2) =>
output2 = output_2;
);
alert(output2);
我在每个订阅的 observable 下方放置了一个警报函数,以检查每个响应返回的输出。
但是当我执行它并检查警告框中的输出时,它给每个都提供了未定义的值。
如何强制 observable 提供来自我的 Web API 的输出?
【问题讨论】:
【参考方案1】:您可以使用诸如switchMap 之类的运算符,根据文档“映射到可观察对象,完成先前的内部可观察对象,发出值”。使用switchMap
它将切换到第二个HttpClient
调用映射第一个可观察对象,当第一个HttpClient
调用的源发出时。如果执行了新的初始/外部请求,它将取消进行中/进行中的请求。
请记住,alert()
语句的设置方式将无法正常工作,因为 alert()
将在请求完成之前执行,因此 undefined
。您需要在subscribe
中执行alert()
或类似操作,或使用do
/tap
等运算符来确保实际返回数据。
import switchMap from 'rxjs/operators';
_httpClient.get('http://localhost:5000/api/mycontroller')
.pipe(
switchMap(output => _httpClient.get('http://localhost:5000/api/mycontroller2' + output))
)
.subscribe(output2 => alert(output2));
如果您需要将输出保存到某个本地类属性,您可以利用do/tap 在数据返回/映射/处理之前/之后执行操作。
import switchMap, tap from 'rxjs/operators';
_httpClient.get('http://localhost:5000/api/mycontroller')
.pipe(
tap(output =>
console.log(output);
this.output = output;
),
switchMap(output => _httpClient.get('http://localhost:5000/api/mycontroller2' + output)),
tap(output2 =>
console.log(output2);
this.output2 = output2;
)
)
.subscribe(output2 => alert(output2));
【讨论】:
实际上,switchMap 的作用与确保第一个请求完成完全相反。如果第一个请求在下一次发射之前没有完成,它实际上会被取消以支持第二个请求。 我会更新答案的语言。无论哪种方式,请求者都需要一个简单的运算符来将连续的 HttpClient 调用链接在一起,这就是 switchMap 所展示的。如果您想展示带有 mergeMap、concatMap、exhaustMap 等的示例,请随意这样做。 @ggradnig 如果您认为这是错误的,一个更有帮助的回应是展示其他方法来顺序进行HttpClient
调用,甚至使用上下文中的运算符处理第一个HttpClient
调用中的错误请求者的问题。谢谢!
嗨,Alex,anwser 当然是对的,但是如果理解不正确,有关 switchMap 的细微细节可能会导致问题。例如,如果在 switchMap 语句之后执行写操作,它将被取消,从而使 API 调用的结果永远丢失。无论如何,您也可以使用 mergeMap 进行顺序调用,因此也可以提及此替代方案。
@AlexanderStaroselsky:如果我需要在第二个 API 调用中重复执行操作,如 switchMap(output => _httpClient.get('localhost:5000/api/mycontroller2' + output[i])) , output[i] 是第一个 API 调用发出的值吗?我的意思是如何根据第一次 api 调用传递的值重复 switchMap 操作?【参考方案2】:
为了完整接受答案,还应提及switchMap
的其他替代方案。
与switchMap
相比,mergeMap
(也称为flatMap
)运算符将不会在“外部 observable”在“inner observable”完成之前第二次发出时被取消.这在HttpClient.get
的情况下可能并不重要,因为它通常只发出一次,因此永远不会再次触发内部可观察对象。
但是,在继续使用 RxJS 运算符时,尤其是在处理顺序数据流时,请注意 switchMap
和 mergeMap
之间的区别。
【讨论】:
mergeMap
确实不是取消http请求,而是导致多余的http请求,因为它会用旧值发出外部请求,当它得到新值时会发出另一个请求。 以上是关于Angular 6:将 Observable 响应传递给另一个 Observable的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Angular 将 Observable 用于 HttpClient?
Angular 6 - 从 observable 获取数据我做错了啥?
无法使用 Observable、Firebase (Angular 6) 为 var 赋值
无法在 RxJs 6 和 Angular 6 中使用 Observable.of
Angular/RxJS 6:如何防止重复的 HTTP 请求?
Angular 6 router.events.filter 'filter' 不存在于类型'Observable<Event>'