Как сделать автосохранение с помощью rxjs? - PullRequest
0 голосов
/ 15 марта 2019

Как выполнить автоматическое сохранение с rxjs, следуя этим критериям?

  • Нажатие на кнопку сохранения должно сделать http запрос на сохранение моих данных (из локальной переменной, а не из формы).
  • Каждые 3000 мс (интервал) должны действовать так же, как я нажал кнопку.
  • Не может быть параллельный HTTP-запрос.Пока запрос не активен, другой запрос не должен выполняться до его завершения.если запрос начался, то все остальные запросы должны ждать в очереди (а затем выполняться по очереди).
  • Кнопка сохранения должна получить высокий приоритет в очереди / execute.

Я хочу использовать мощность rxjs, поэтому было бы неплохо сделать это с помощью операторов rxjs, а нелокальные переменные (if (this.requestStart === true)).

Это то, чего я хочу достичь до сих пор.Любая помощь будет оценена

import { Component, Input } from '@angular/core';
import {Observable, interval} from 'rxjs';

@Component({
  selector: 'hello',
  template: `

  <h1>Hello {{name}}!</h1>
  <button (click)="save()">save</button>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;

  constructor() {
    interval(3000)
      .subscribe(val => this.makeRequest());

  }

  save() {
    this.makeRequest().subscribe(res => {
      console.log({ res });
    });
  }

  makeRequest() {
    return Observable.create((observer) => {
      setTimeout(() => {
        observer.next({ save: true });
        observer.complete();
      }, 5000);
    });
  }
}

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

Вы можете использовать switchMap и concatMap для этого случая:

manualSave$ = new Subject<any>();

constructor(private http: HttpClient) { }

ngOnInit() {
  this.manualSave$.pipe(
    switchMap(() => timer(0, 3 * 1000)),
    concatMap(() => this.makeRequest())
  ).subscribe(result => {
    console.log(result);
  })
  this.manualSave$.next(); // to start it off
}

save() {
  this.manualSave$.next();
}

makeRequest() {
  const url = 'https://jsonplaceholder.typicode.com/todos/1';
  return this.http.get(url);
}

Что происходит, это:

---1---2---3---4---5---6---...
-----X------X------------X-...
      switchMap                // Preserves 3 second interval after every save
                               // Unless interrupted by a manual save
---A-B---A--B---A---A---AB-... // A: http request generated from autosave
                               // B: http request generated from manual save
      concatMap
---ResResResRes-Res-Res-ResRes-... 
                   // Concats one request only after the last one is finished

Я предпочитаю использовать switchMap вместо слияния, потому что merge делает это:

---1----2----3----4----5----6---...
-----X--------X-------------X---...
      merge
---1-X--2----3X---4----5----(6X)...

Пока switchMap отменяет предыдущие значения и делает это:

---1----2----3----4----5----6---...
-----X--------X-------------X---...
      switchMap
---1-X----2---X----4----5---X---...

только делает необходимое количество запросов.

0 голосов
/ 15 марта 2019

Вы можете использовать merge вместе с exhaustMap, чтобы убедиться, что обрабатывается только один запрос за раз.

Что-то вроде:

// Get a btn reference
const btnEl = document.getElementById('send-btn');

merge(
  fromEvent(btnEl, 'click'),
  interval(3000)
).pipe(
  concatMap(_ => this.makeRequest())
)
.subscribe(res => {
  console.log({ res });
});

Достигнуть приоритизации будет непросто, rxjs в этом смысле не строится вокруг очередей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...