【问题标题】:Angular 6: Passing Observable response to another ObservableAngular 6:将 Observable 响应传递给另一个 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 的输出?

【问题讨论】:

    标签: angular typescript asp.net-web-api rxjs


    【解决方案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 运算符时,尤其是在处理顺序数据流时,请注意 switchMapmergeMap 之间的区别。

    【讨论】:

    • mergeMap确实不是取消http请求,而是导致多余的http请求,因为它会用旧值发出外部请求,当它得到新值时会发出另一个请求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2020-12-08
    • 2018-01-31
    • 1970-01-01
    相关资源
    最近更新 更多