RxJS - Как заменить обратный вызов в подписке на наблюдаемый - PullRequest
0 голосов
/ 02 июля 2018

Недавно мой коллега реализовал обратный вызов в подписке в нашем приложении 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. Но после того, как я реализовал / реорганизовал код, он не кажется лучшим решением. Код теперь выглядит намного сложнее. Нужно ли привести трубку к обещанию и вернуть ее как наблюдаемую?

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? Или мой коллега имел право использовать простой обратный вызов?

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

ИМХО обратный вызов - самое простое решение. Полный обработчик, вероятно, будет лучшим местом для его вызова. Если вы хотите использовать наблюдаемые, я бы придерживался семантики потока.

Если ваша цель - обработать успешный случай, и вы не хотите извлекать данные из функции, тогда вы можете вернуть пустую, завершенную наблюдаемую. В случае ошибки вы можете либо позволить ей пройти, либо заменить ее пустой наблюдаемой, которая заканчивается ошибкой. Это похоже на 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.

0 голосов
/ 02 июля 2018

Вам не нужно приводить к Promise, а затем снова приводить к Observable. Также посмотрите на функцию map. Почему вы возвращаете true с него? Функция 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...