[英]Angular RXJS Polling from within nested observables
我有一個由解析器用來生成和返回報告的服務。
服務中的初始獲取調用 REST 端點/report
,它啟動服務器上的工作作業,因為報告是處理器密集型的,運行時間超過 30 秒。 report
端點返回工作作業的 ID。
然后,我需要使用作業的相關 id 輪詢工人作業 REST 端點/job/job_id
。 我繼續輪詢,直到它返回“已完成”狀態,並包含完成的報告。
這個最終輸出然后從服務返回,解析器使用它。
我一直無法通過投票來解決這個問題。 我將初始報告端點的響應通過管道傳輸到 switchMap 中,然后使用間隔每 500 毫秒重復輪詢/job/job_id
端點。 然后我嘗試切換映射投票響應並在完成時返回。 這是我第一次使用 switchMap 和輪詢,所以我不確定我是否正確使用它。
這是我對代碼的最新嘗試:
getDepartmentReport() {
return this.http
.get<any>(reportUrl, this.getAuthOptions(true))
.pipe(switchMap(initialResponse => {
interval(500).pipe(
switchMap(() => {
return this.http.get<any>(workerUrl + initialResponse.id, this.getAuthOptions(true))
.pipe(
switchMap(pollResponse => {
if(pollResponse.state === 'completed') {
return pollResponse;
}
})
}));
}));
}
這實際上不會編譯。 它給出了以下錯誤:
Argument of type '(initialResponse: any) => void' is not assignable to parameter of type '(value: any, index: number) => ObservableInput<any>'.
Type 'void' is not assignable to type 'ObservableInput<any>'.
56 .pipe(switchMap(initialResponse => {
我認為這是因為在不完整的輪詢響應時,沒有返回語句來處理這種情況,並且返回一個空值。
有人有任何想法嗎? 我難住了。
這是一個有趣的問題。
您收到該錯誤是因為switchMap
必須返回一個Observable 。 在你的代碼中,你沒有返回任何東西,你只是開始一個間隔。
您還必須告訴您的時間間隔何時停止輪詢。 這可以在takeWhile
運算符的幫助下實現。 為了將事情分開一點,我創建了一個自定義運算符,輪詢將在其中進行。 這樣做,您也可以在其他地方重用此運算符。
這是我的方法:
// ===== Server =====
let crtReportId = 1;
let crtReportStatus: { status: string, id: number };
const getReportFromBE = () => {
let initialId = crtReportId;
crtReportStatus = { status: 'pending', id: initialId };
// It takes some time...
timer(2000)
.subscribe(() => crtReportStatus = { status: 'completed', id: initialId })
return of(crtReportId++);
}
const getWorkerStatus = id => of(crtReportStatus);
// ===== Client =====
type CustomPollOperator = (data: any, cond: (d) => boolean, ms: number) => Observable<any>
const pollFor: CustomPollOperator = (data, cond, ms) => {
let shouldPoll = true;
return interval(ms)
.pipe(
tap(() => console.warn('pooling', shouldPoll)),
takeWhile(() => shouldPoll),
switchMap(() => getWorkerStatus(data)),
tap(res => {
if (cond(res)) {
shouldPoll = false;
}
})
)
}
const isWorkerCompleted = w => w.status === 'completed';
const getReports = () => {
return getReportFromBE()
.pipe(
switchMap(workerId => pollFor(workerId,isWorkerCompleted, 200))
)
}
getReports().subscribe((res) => console.log('result', res))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.