Сначала Rxjs опрашивает объект, затем, при необходимости, повторяет опрос на основе статуса объекта

#angular #rxjs

#angular #rxjs

Вопрос:

Я хотел бы знать, как лучше всего выполнить следующее в angular RxJS.

  1. при загрузке страницы мне нужно по протоколу http получить подробную информацию об объекте
  2. основываясь на статусе объекта, мне нужно либо повторно опросить статус объекта, пока он не будет ГОТОВ, если он не готов. Или прекратите опрос, если он готов.
  3. Статус объекта может быть изменен с «готов» на «Не готов» или «не готов» на «готов» в любое время. Это может быть задано по результатам опроса или задано пользователем по запросу, когда пользователь захочет.

Я пробовал что-то похожее на следующее, но чувствую, что это не лучшее решение:

 this.http.getObjectDetails(this.id).subscribe()

timer(1000, 1000)
      .pipe(
        filter(() => this.object.status != 'READY'),
        concatMap(() => {
          return this.http.checkObjectStatus(this.id)
        })
      ).subscribe()

 

Во-первых, он не объединяет две подписки, а во-вторых, я не уверен, что он сможет справиться с ситуацией, когда статус изменился с ready на not ready.

Спасибо

Комментарии:

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

2. @ArashHatami. У меня есть кнопка пользовательского интерфейса, позволяющая пользователю проверять принудительную проверку.

Ответ №1:

Вы можете использовать оператор expand для простого «условного повтора» поведения.

 this.http.getObjectDetails(this.id).subscribe()
let request = this.http.checkObjectStatus(this.id);

request.pipe(
  expand(
    res => {
      if (res.status == 'READY') {
        return empty();
      }
      else {
        return timer(1000).pipe(
          map(() => {
            return request
          })
        );
      }
    }
  ),
).subscribe(res => { });
 

также импортируйте

 import { empty } from 'rxjs';
import { expand } from 'rxjs/operators';
 

Комментарии:

1. this.request не определено после подписки. Ваш код выдаст сообщение об ошибке

2. @JingshaoChen это образец :)) не для копирования и вставки, хорошо, я отредактирую его сейчас

3. Ваш ответ вызывает запрос в цикле и запускает кучу дополнительных запросов каждую секунду. и сначала он не вызывает get details

4. @JingshaoChen Вы правы, проверьте это еще раз, спасибо

5. это все еще не гарантирует, что статус get будет запущен после получения сведений. Допустим, получение сведений задерживается на 5 секунд, получение статуса будет выполняться 5 раз, когда получение сведений разрешится.

Ответ №2:

Вы могли бы сделать это с помощью функции, которая вызывает себя рекурсивно, пока ответ не будет готов.

 const { of, iif } = rxjs;
const { switchMap, tap, delay } = rxjs.operators;

const http = url => of({ STATUS: (Math.random() > .7) ? 'READY' : 'NOT READY' })

const getObjectDetails = (id) => http(`url/{id}`).pipe(
  tap(result => { console.log(result.STATUS); }),
  switchMap(result => iif(() => result.STATUS === 'READY', of(result), getObjectDetails(id)))
);

getObjectDetails(1).subscribe(result => { console.log('finished'); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.3/rxjs.umd.min.js"></script>