可以通过redux观察到的使用RxJS发出Ajax调用的进度操作

时间:2018-12-14 17:27:16

标签: redux rxjs redux-observable

我一直在努力解决这个问题,觉得自己有一个基本的误解。我正在使用redux-observable中的React库,该库将reduxRxJS粘合在一起以处理异步。我的问题是我必须处理大量上载,并且要在加载文件时显示进度。

函数uploadFileEpic需要返回一个Observable<Action>才能与redux-observable一起使用。 uploadObservable代表我要完成的工作流程。如果我只返回uploadObservable,则上传成功,但在handleUploadFileProgress调用中没有从progressSubscriber收到任何ajax动作。理想情况下,progressSubscriber将元素添加到另一个我可以与uploadObservable合并的观察对象中。您看到我在这里尝试使用merge,但是TypeScript编译器抱怨说该返回值无法分配给ObservableInput

我一直绕圈子走,所以我觉得我的理解必须从根本上偏离。我觉得这里缺少一些简单的RxJS魔术。感谢您的帮助!

import { Observable, Observer, Subscriber, Subject, of } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { ofType } from 'redux-observable';
import { catchError, delay, map, mergeMap, tap, merge } from 'rxjs/operators';
import { apis } from '../../config';

export const enum ActionType {
  InitialFileUpload
  FileProgress
  UploadFileSuccess
  UploadFileFail
}

const handleInitialFileUpload = (file: File, timeLimit: number) => ({
  type: ActionType.InitialFileUpload,
  file,
  timeLimit
})

const handleFileProgress = (file: File, percentComplete: number) => ({
  type: ActionType.FileProgress,
  file,
  percentComplete
})

const handleUploadFileSuccess = (file: File, timeLimit: number) => ({
  type: ActionType.UploadFileSuccess,
  file,
  timeLimit
})

const handleUploadFileFail = (file: File, timeLimit: number) => ({
  type: ActionType.UploadFileFail,
  file,
  timeLimit
})


export const uploadFileEpic= action$ =>
  action$.pipe(
    ofType(ActionType.InitialFileUpload),
    mergeMap((action: any) => {
      const { file, timeLimit } = action;
      const data = new FormData()
      data.append('importFile', file, file.name)
      data.append('timeLimit', timeLimit)
      const progressSubject = new Subject();

      const ajaxRequest = {
        url: apis.gateway.run,
        method: 'POST',
        body: data,
        headers: {},
        progressSubscriber: Subscriber.create(
          (e: ProgressEvent) => {
            const percentComplete = Math.round((e.loaded / e.total) * 100)
            console.log("Progress event")
            progressSubject.next(handleUploadFileProgress(file, percentComplete))
          }
        )
      }

      const uploadObservable = ajax(ajaxRequest)
        .pipe(
          map(res => handleUploadFileSuccess(file)),
          delay(SUCCESSFUL_UPLOAD_NOTIFICATION_LENGTH),
          map(() => handleUploadFileRemove(file)),
          catchError(error => of(handleUploadFileFail(file, error.response)))
        )

      return merge(uploadObservable, progressSubject)
      }
    )
  )

1 个答案:

答案 0 :(得分:0)

您似乎正在从merge导入rxjs/operators。此处,merge被视为运算符,因此返回OperatorFunction。通过简单地从rxjs进行导入,您将获得静态合并,该合并正确地返回了Observable,该合并将由您的mergeMap展平。