Как я могу опросить результаты работы и прекратить работу, если статус сделан с помощью rxjs6? - PullRequest
0 голосов
/ 18 января 2019

Представьте себе сервис с тремя конечными точками.

  1. Отправь работу и верни ID работы
  2. Подать запрос статуса и вернуть статус
  3. Отправьте запрос результатов и получите результаты

Мне нужно решение, чтобы отправить работу и опросить результаты, пока статус работы не будет выполнен. Поскольку конечные точки состояния и результатов независимы, мне нужно убедиться, что я сделал один последний запрос результатов после того, как было определено, что статус DONE.

Я пытался использовать много операторов rxjs, но безрезультатно. Я могу сделать опрос легким, но самая сложная часть - остановить опрос точно в нужное время. Когда я использую takeWhile или takeUntil, мой опрос останавливается, прежде чем я могу получить результаты.

return submitJob(request).pipe(
  delay(500), // Delay start of poll
  switchMap(job => getResults(job).pipe(
    repeatWhen(c => c.pipe(delay(1000))), // Keep getting results every second
    takeUntil(getStatus(job).pipe(
      filter(status => status.done)
    ))
  )
);

Проблема в том, что статус Задания выполняется немедленно и вызов результатов отменяется. Мой код никогда не отправляет запрос результатов. Мне нужно сделать хотя бы один звонок, чтобы получить результаты ПОСЛЕ того, как статус возвращается, как сделано.

1 Ответ

0 голосов
/ 19 января 2019

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

const { of, interval, timer } = rxjs; // = require("rxjs")
const { tap, take, filter, mergeMap } = rxjs.operators; // = require("rxjs/operators")

// simulate API methods
const submitJob = id => of('newjob');
let tries = 0;
function getStatus() {
  tries += 1;
  if (tries === 5) return of('done');
  return of('working...');
}
const getResult = () => of('result');

const job$ = submitJob().pipe(
  tap(e => console.log('started job: ', e)),
  // wait 500ms and then make request every 1000ms
  mergeMap(e => timer(500, 1000).pipe(
    // request status every 1 second
    mergeMap(t => getStatus()),
    tap(e => console.log('status: ', e)),
    // when 1 'done' received - stop polling
    filter(status => status === 'done'),
    take(1)
  )),
  mergeMap(e => getResult())
)

job$.subscribe(e => console.log('completed: ', e));
<script src="https://unpkg.com/rxjs@6.3.3/bundles/rxjs.umd.min.js"></script>
...