简体   繁体   English

RxJS-如何用可观察对象替换订阅中的回调

[英]RxJS - How to replace a Callback in a Subscription with an Observable

Recently a colleague of mine implemented a callback in a Subscription in our Angular 6 application like this: 最近,我的一位同事在Angular 6应用程序的Subscription中实现了回调,如下所示:

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
  });
}

I thought it would be better to solve this "problem" with an RxJS Observable instead. 我认为最好用RxJS Observable解决此“问题”。 But after I implemented/refactored the code it doesn't seem to be the better solution. 但是在实现/重构代码后,它似乎并不是更好的解决方案。 The code looks much more complicated now. 该代码现在看起来更加复杂。 Is it necessary to cast the pipe to a promise and return it as an observable? 是否有必要将管道投放到承诺中并以可观察的方式返回?

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);
}

Is there a better way to solve this problem with Observables? 使用Observables是否有更好的方法解决此问题? Or was my colleague right to use a simple callback? 还是我的同事有权使用简单的回调?

You don't need to cast to Promise and then again cast into Observable . 您无需强制转换为Promise ,然后再次强制转换为Observable Also look at the map function. 还要看map功能。 Why you return true from it ? 为什么你从中返回true map function is designed for changing coming data and pass changed ones next. map功能旨在更改即将到来的数据,然后再传递已更改的数据。

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;
}

IMHO the callback is the simplest solution. 恕我直言,回调是最简单的解决方案。 The complete handler would probably be a better place to call it. 完整的处理程序可能是一个更好的地方。 If you want to use observables then I would adhere to the stream semantics. 如果您想使用可观察变量,那么我将坚持使用流语义。

If your goal is to handle the success case and you don't want to get data out of the function then you can return an empty, completed observable. 如果您的目标是处理成功案例,并且不想从函数中获取数据,则可以返回一个空的,完整的可观察值。 I case of an error you can either let it pass through or replace it with an empty observable, that terminates with an error. 如果发生错误,您可以让它通过,也可以将其替换为以错误结尾的空的可观察对象。 It is similar to observable.of(true / false) , but relies on the stream semantics instead of arbitrary values. 它类似于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}
       );
    }

As you can see it's still much more code than in the callback solution. 如您所见,与回调解决方案相比,它的代码仍然更多。 But if you add an error callback one day it might be an interesting option. 但是,如果有一天添加了错误回调,这可能是一个有趣的选择。 The upside of the observable solution: No ifs. 可观察到的解决方案的好处是:没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM