Me gustaría tener la capacidad de reinicializar un objeto Observable. No sé si "reinicializar" es el término actual, pero lo que quiero decir con eso es que me gustaría actualizar los datos

  1. sin crear un nuevo objeto Observable, y
  2. sin crear nuevas suscripciones (las suscripciones existentes al objeto Observable existente deberían funcionar sin problemas)

He creado dos fragmentos de código de muestra. Mi suposición es que la solución debería ser la misma (o muy similar) para ambos fragmentos de código. (Sin embargo, mi suposición puede estar equivocada)

Código de muestra sin angular

let rxjs = require("rxjs");
let op = require("rxjs/operators");

let observable = rxjs.Observable.create(function (observer) {
  let data = new Date().toString();
  console.log(`Initializer executed. Data: ${data}`);
  let counter = 0;
  setInterval(function () {
    observer.next(data + " - " + counter.toString());
    counter++;
  }, 500);
}).pipe(op.shareReplay());

const s1 = observable.subscribe((val) => console.log("subscriber1 - " + val));
setTimeout(() => {
  const s2 = observable.subscribe((val) => console.log("subscriber2 - " + val));
}, 2000);
setTimeout(() => {
  // TODO:
  // refresh the 'currentTime' value within the observable here
  // without creating a new Observable object or creating new subscriptions
}, 10000);

Código de muestra con Angular

@Injectable({
  providedIn: 'root',
})
export class MyService {
  private url = 'http://mydummydomain.com/api/entries';
  private data$: Observable<any>;

  constructor(private http: HttpClient) {
    this.data$ = this.http.get(this.url).pipe(
      shareReplay(1)
    );
  }

  getData(): Observable<any> {
    return this.data$;
  }
  
  reloadData() {
    // TODO:
    // Refresh data from the url
    // Theoretically this should be a function with no input parameters and no return value
  }
}

Gracias

0
yellowtail 23 jun. 2020 a las 15:16

2 respuestas

Probar esto

refresh$ = new Subject<void>();
data$ = this.refresh$.pipe(startWith(null), switchMap(() => this.http.get(this.url)), shareReplay(1));


reloadData() {
  refresh$.next();
}
0
Andrei 23 jun. 2020 a las 12:19

Creo que BehaivorSubject puede resolver su problema sin crear nuevos observables, pero aconsejaría que usar ngrx o mobx para trabajar con datos sea mucho más conveniente. ¿Y no puedo entender por qué configura los datos es privado y crea getter? práctica normal de usar public para variables en una vista.

@Injectable({
  providedIn: 'root',
})
export class MyService {
  private url = 'http://mydummydomain.com/api/entries';
  public data$: BehaviorSubject<any> = new BehaviorSubject(null);

  constructor(private http: HttpClient) {
    this.http.get(this.url).pipe(
      take(1)
    ).subscribe((data) => {
      this.data$.next(data);
    });
  }
  
  reloadData() {
    this.http.get(this.url).pipe(
      take(1)
    ).subscribe((data) => {
      this.data$.next(data);
    });
  }
}

Es mejor mover su lógica con API al servicio, puede usar los datos en varios componentes y puede usarlos de manera más eficiente cuando los datos se almacenan en un solo lugar.

0
Валера Битковский 23 jun. 2020 a las 12:26