#angular #rxjs
#angular #rxjs
Вопрос:
Я хотел бы знать, как лучше всего выполнить следующее в angular RxJS.
- при загрузке страницы мне нужно по протоколу http получить подробную информацию об объекте
- основываясь на статусе объекта, мне нужно либо повторно опросить статус объекта, пока он не будет ГОТОВ, если он не готов. Или прекратите опрос, если он готов.
- Статус объекта может быть изменен с «готов» на «Не готов» или «не готов» на «готов» в любое время. Это может быть задано по результатам опроса или задано пользователем по запросу, когда пользователь захочет.
Я пробовал что-то похожее на следующее, но чувствую, что это не лучшее решение:
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>