将承诺函数转换为可观察的

时间:2021-07-12 20:35:54

标签: typescript promise rxjs observable

我有一段代码,它使用并返回一个承诺。但是,我想将其转换为可观察的。请指教。

原始代码:

export const uploadMultipleFilesToAzure = (
  uploadData: Omit<UploadMultipleToAzure, 'id'>[],
  handleProgress: (
    loadedBytes: number,
    fileData: UploadMultipleToAzure['fileData'],
    uploadId: Upload['id']
  ) => void,
  individualCallback: Function
): Promise<BlockBlobUploadHeaders[]> => {
  const PIPELINE: Pipeline = newPipeline(new AnonymousCredential(), {
    retryOptions: { maxTries: 4 }, // Retry options
    keepAliveOptions: {
      // Keep alive is enabled by default, disable keep alive by setting false
      enable: false,
    },
  });

  const promises: Promise<BlobUploadCommonResponse>[] = [];
  forEach(uploadData, (uploadItem) => {
    let blockBlobClient: BlockBlobClient = new BlockBlobClient(
      uploadItem.BlobURL,
      PIPELINE
    );
    promises.push(
      (
        blockBlobClient.uploadData(uploadItem.fileData as Blob, {
          blockSize:
            (uploadItem.fileData as Blob).size > 1024 * 1024 * 32
              ? 1024 * 1024 * 4
              : 1024 * 512,
          maxSingleShotSize: 1024 * 512,
          concurrency: 20, // 20 concurrency,
          onProgress: (ev: TransferProgressEvent) =>
            handleProgress(
              ev.loadedBytes / (uploadItem.fileData as Blob).size,
              uploadItem.fileData,
              uploadItem.id
            ),
        }) as any
      ).then(() => {
        individualCallback(uploadItem);
      })
    );
  });
  return Promise.all(promises);
};

1 个答案:

答案 0 :(得分:0)

在我看来,这就像一个简单的 forkJoin 情况。

简化,你有:

const uploadMultipleFilesToAzure = (uploads: any[]) =>
  forkJoin(uploads.map(upload => 
    upload.somethingReturningPromise(prms)
  );

这只是将 Promises.all 替换为 forkJoin。 forkJoin 可以将 promise 作为输入,并会发出带有结果数组的单个事件。

如果你有内部的“then”,它就会变成一个 xMap - 让我们假设 mergeMap。您现在需要 from() 将 promise 转换为 observable:

const uploadMultipleFilesToAzure = (uploads: any[]) =>
  forkJoin(uploads.map(upload => 
    from(upload.somethingReturningPromise(prms)).pipe(
      mergeMap( ()=> individualCallback(uploadItem);
    )
  );

最后,如果您使用 forkJoin 或 from() ,那么在调用此函数(以创建 observable)时将调用 promise,而不是在订阅 observable 时调用。出于这个原因,通常最好使用 defer() 代替:

  const uploadMultipleFilesToAzure = (uploads: any[]) =>
    forkJoin(uploads.map(upload => 
      defer(() => upload.somethingReturningPromise(prms)).pipe(
        mergeMap( ()=> individualCallback(uploadItem);
      )
    );