Экспорт большого отчёта или импорт CSV не завершается мгновенно. Backend отдаёт jobId, и нужно опрашивать /jobs/{id} до тех пор, пока status не станет done. Тогда забираем файл.
Какую проблему решаем
setInterval запускает новый poll, не дожидаясь предыдущего ответа — на медленной сети опросов будет больше, чем ответов. Сам интервал нужно вручную чистить при destroy, success и error. Легко забыть и продолжать polling после ухода со страницы.
Операторы и зачем они нужны
switchMap — от startJob переходим к polling stream.
expand — рекурсивно создаёт следующий poll ТОЛЬКО после ответа на текущий. Никаких параллельных опросов.
takeWhile(status => !done, true) — пропускаем done через себя (inclusive=true) и завершаем polling.
last — финальный done-status.
map — отдаём файл из финального ответа.
Подводные камни
interval вместо expand — будут параллельные опросы, и backend получит лавину запросов на медленной сети.
repeat без условия done — бесконечный polling. Job завершилась, а вы её опрашиваете до сих пор.
Забыть true у takeWhile — финальный done не пройдёт downstream, last не увидит ничего и stream повиснет.
Что в итоге получаем
Polling сам себя завершает на done и отдаёт один финальный результат. Никаких ручных таймеров и флагов.