【问题标题】:RxJS - How to replace a Callback in a Subscription with an ObservableRxJS - 如何用 Observable 替换订阅中的回调
【发布时间】:2018-12-10 07:23:17
【问题描述】:

最近我的一位同事在我们的 Angular 6 应用程序中的订阅中实现了一个回调,如下所示:

callDoSomething() {
  this.doSomething(() => { 
    // logic from callback
   });
}

public doSomething(callback: any) {
  this.http.get('/api/doSomething').subscribe(data => {
    // do something with data
    if (callback) {
      callback();
    }
  }, error => {
    // do something with error
  });
}

我认为用 RxJS Observable 来解决这个“问题”会更好。但是在我实现/重构代码之后,它似乎并不是更好的解决方案。代码现在看起来要复杂得多。是否有必要将管道转换为 Promise 并将其作为可观察对象返回?

import { Observable, of as observableOf, from as observableFrom } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

callDoSomething() {
    this.doSomething().subscribe((result) => {
    if (result) {
        // logic from callback
    }
    });
}

public doSomething() {
    let promise = this.http.get('/api/doSomething').pipe(
    map(data => {
        // do something with data
        return observableOf(true);
    }),
    catchError((error) => {
        // do something with error
        return observableOf(false);
    })
    ).toPromise()

    return observableFrom(promise);
}

有没有更好的方法来使用 Observables 解决这个问题?还是我的同事有权使用简单的回调?

【问题讨论】:

  • 在您的第一个示例中,无论请求是否成功,都会调用 callback。这是故意的吗?如果这是你的第二个例子没有多大意义。
  • 不,这不是故意的。这是我同事实施中的一个错误。只有在请求成功时才应调用回调。我会在我的问题中解决它。

标签: angular rxjs


【解决方案1】:

恕我直言,回调是最简单的解决方案。完整的处理程序可能是调用它的更好地方。如果你想使用 observables,那么我会坚持流语义。

如果您的目标是处理成功案例并且您不想从函数中获取数据,那么您可以返回一个空的、已完成的 observable。如果出现错误,您可以让它通过或用一个空的 observable 替换它,它会以错误终止。它类似于observable.of(true / false),但依赖于流语义而不是任意值。

    doSomething() {
     return this.http.get('/api/doSomething').pipe(
        flatMap(data => {
          // do something with data
          return empty();
        }),
        catchError((error) => {
          // do something with error
          return throwError(error); //instead of error pass whatever you like
        })
      );
    }

    callDoSomething() {
      this.doSomething()
       .subscribe(
         undefined, //we don't handle data
         undefined, //we don't handle errors
         () => {// logic from callback}
       );
    }

正如您所见,它仍然比回调解决方案中的代码多得多。但是如果有一天你添加一个错误回调,它可能是一个有趣的选择。可观察解决方案的优点:没有 ifs。

【讨论】:

    【解决方案2】:

    您无需先转换为Promise,然后再转换为Observable。另请查看map 函数。为什么你从它返回truemap 函数是为改变传入的数据而设计的,然后传递改变的数据。

    public doSomething() {
        let observable= this.http.get('/api/doSomething').pipe(
        map(data => {
            // do something with data
            return observableOf(true);
        }),
        catchError((error) => {
            // do something with error
            return observableOf(false);
        }));
    
        return observable;
    }
    

    【讨论】:

    • 我不知道为什么我不只是返回管道...我知道 map 函数用于更改数据并将更改传递给下一个运算符,但我不想要数据离开我的“doSomething”功能。我查看了文档,但不确定还有什么其他运算符更适合。
    猜你喜欢
    • 1970-01-01
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 2017-10-10
    • 2023-04-07
    • 1970-01-01
    • 2016-07-07
    相关资源
    最近更新 更多