【问题标题】:understanding of switchmap in rxjsrxjs中switchmap的理解
【发布时间】:2021-04-15 17:02:10
【问题描述】:

我是 rxjs 的新手。我正在尝试了解 switchmap 功能。为了便于理解,我写了以下代码。

const fun1 = () => {
    return new Promise((resolve, reject) => resolve("Fun1"));
  };
  const fun2 = () => {
    return new Promise((resolve, reject) => resolve("Fun2"));
  };
  const fun3 = () => {
    return new Promise((resolve, reject) => resolve("Fun3"));
  };

  const observer = from(fun()).pipe(
    switchMap((result1) => {
      return from(fun1());
    }),
    switchMap((result2) => { 
      return from(fun2())
    }),
    switchMap((result3) => {
      return from(fun3());
    })
  );
  observer.subscribe(
    (val) => console.log("Val =", val),
    (error) => console.log("Error = ", error),
    () => console.log("Completed")
  );

以上代码将 Fun3 返回给订阅者。

但我的期望是,如果 fun2() 返回带有“Fun2”字符串的承诺,那么代码不应使用 from(fun3()); 执行 switchmap;并且代码应该向订阅者返回“Fun2。我怎样才能在上面提到的代码中实现这个功能。

【问题讨论】:

    标签: node.js reactjs angularjs react-native rxjs


    【解决方案1】:

    我已经重新编写了您的代码,因此可能更容易理解为什么您总是得到“fun3”。

    const fun1 = () => of("Fun1");
    const fun2 = () => of("Fun2");
    const fun3 = () => of("Fun3");
    
    const observable = from(fun()).pipe(
      switchMap(_ => fun1()),
      switchMap(_ => fun2()),
      switchMap(_ => fun3()),
    );
    
    observer.subscribe({
      next: val => console.log("Val =", val),
      error: err => console.log("Error = ", err),
      complete: () => console.log("Completed")
    });
    

    首先,请注意我的 switchMaps 是如何忽略他们的输入的?这应该会提示您忽略前一个可观察对象的“返回值”。

    switchMap(_ => fun1()) 说“只要源 observable 发出一个值(我不在乎这个值是什么),然后订阅 fun1 返回的 observable。”

    这是另一个例子:

    const observable = from(fun()).pipe(
      switchMap(result => result == "Fun2"? of(result) : fun1()),
      switchMap(result => result == "Fun2"? of(result) : fun2()),
      switchMap(result => result == "Fun2"? of(result) : fun3()),
    );
    

    现在您有了正在检查中间结果的可观察对象。

    • 第一个结果是fun() 发出的任何内容,如果不是"Fun2",则调用fun1()
    • 第二个结果是"Fun1",因为它也不是"Fun2",所以调用fun2()
    • 第三个结果是"Fun2"!啊哈!现在我们返回一个发出 "Fun2" 而不是调用 fun3() 的 observable

    【讨论】:

      【解决方案2】:

      switchMap 和exhaustMap 或mergeMap 一样,用于扁平化可观察对象的可观察对象。 switchMap 的特殊之处在于,如果您的源 observable(在您的情况下:from(fun()))发出一个新值,则 switchMap 运算符将在订阅新的内部 observable 之前取消订阅前一个内部 observable。 因此,您将始终只有一个内部订阅。 这个 ng-conf 演讲完美地解释了它:

      https://www.youtube.com/watch?v=rUZ9CjcaCEw

      在您的示例中,您使用管道函数来管道三个 switchMap。您的 observable 的值(在您的 subscribe 方法中)将始终是您在管道函数中进行的最后一次转换(在您的情况下为(“Fun3”))。

      对于您的具体示例,您可以执行以下操作:

      const observer = from(fun).pipe(
          switchMap((result2) => { 
            return from(fun2()).pipe(
              catchError(error => fun3())
            )
          })
        );
      

      这种方式 fun3() 只有在 fun2() 拒绝时才会被调用,否则您的订阅者将收到 fun2() 的结果。

      但我强烈建议您观看只有 20 分钟的演讲,并真正解释了 switchMap 的作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-14
        • 2019-10-12
        • 1970-01-01
        • 1970-01-01
        • 2018-09-16
        相关资源
        最近更新 更多