【问题标题】:RXJS: Requests by queue - ForkJoinRXJS:按队列请求 - ForkJoin
【发布时间】:2021-05-26 16:08:08
【问题描述】:

我正在尝试按队列上传图片。目前,我需要按五次上传图片

例如,如果我有 10 张图片,我需要上传 5 张图片,当上传这 5 张图片时,我需要再次请求剩余的 5 张图片。

经过大量搜索和测试大量 RXJS 运算符/函数后,我可以通过(concat - RXJS 函数)和(scan 和 last - RXJS 运算符)找到这个解决方案:

在 index.html 中

// added chunk function into array protptype
 Array.prototype.chunk = function (chunkSize) {
     var R = [];
     for (var i = 0; i < this.length; i += chunkSize) {
        R.push(this.slice(i, i + chunkSize));
     }

     return R;
  }

在服务中


  uploadImages(images: File[]) {
    const requestsList = images.map(file => {
      return this._baseAPI.filesManagement.uploadFile({ file, 'image' })
    });

      // custom function: added manualy in index.html
      const requestChunks = requestsList.chunk(5);  
 
      const requestsByChunks = requestChunks.map(reqs => forkJoin(reqs));

      return concat(...requestsByChunks).pipe(
         // transforming and collecting all of the responses
          scan((acc, response: {folder: string; image: string}[]) => {
            response.forEach(itemResponse => {
              if (!acc[itemResponse.folder]) { acc[itemResponse.folder] = []; }
              acc[itemResponse.folder].push(itemResponse.image);
            });
            return acc;
          },
            {} as { [key: string]: string }),
          // getting the callected response only once at the end
          last()
       );
  }

使用示例

this.uploadImages(/* Array of files*/).subscribe(response => {console.log(response); })

我想知道对于这些情况是否有任何其他解决方案或最佳实践。也许我错过了一些东西,因为我不确定这是最好的解决方案?

还有:这里是当前逻辑的模拟:https://stackblitz.com/edit/rxjs-kcnrgn?file=index.ts

感谢大家的宝贵时间。

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    以下是我在更倾向于 RxJS 和不可变对象/数组时的做法。

    可能需要一些调整,因为我没有真正测试过。和你做的基本一样。

    uploadImages(images: File[]) {
      return from(images).pipe(
        map(file => this._baseAPI.filesManagement.uploadFile({ file, 'image' })),
        // chunk 5
        bufferCount(5), 
        // perform the requests 5 at a time
        concatMap(reqs => forkJoin(reqs)), 
        // like last, but creates an array of emissions (which are themselves arrays of size 5)
        toArray(), 
        // Flatten the array of arrays into a single array with all the results
        map(arr => arr.flat()),
        // transforming all of the responses
        map(res => res.reduce((
            acc: { [key: string]: string[] }, 
            {folder, image}: { folder: string; image: string }
          ) => ({...acc, folder: [...acc[folder] || [], image] }),
          {}
        ))
      );
    }
    

    【讨论】:

    • 哦,太好了,谢谢。让我测试一下然后回来。
    • 非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多