【问题标题】:How can i await for file to upload so i can upload next image with params我如何等待文件上传,以便我可以使用参数上传下一张图片
【发布时间】:2021-11-27 07:49:48
【问题描述】:

我正在使用拖放文件上传多张图片。

ngx-file-drop

如何使用异步等待来上传图片,因为我想将参数发送到从第一个请求返回的下一张图片。

从第一个请求返回的post_id 应该与所有下一个图像一起发送。

这是正在做的事情,但它没有等待:

dropped(files: NgxFileDropEntry[]) {
    this.files = files;
    for (const droppedFile of files) {

      // Is it a file?
      if (droppedFile.fileEntry.isFile) {
        const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
        fileEntry.file(async (file: File) => {
          // Here you can access the real file
          console.log(droppedFile.relativePath, file);

          await new Promise((resolve, reject) => {
            this.http.uploadImages(file, 'UploadImage', this.postId).subscribe((res: any) => {
              if (res.status == true) {
                resolve(true);
                this.postId = res.data.post_id; // i want to send this ID in next request. 
              } else {
                reject();
                console.log(res.message);
              }
            })
          });


        });
      } else {
        // It was a directory (empty directories are added, otherwise only files)
        const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry;
        console.log(droppedFile.relativePath, fileEntry);
      }
    }
  }

【问题讨论】:

  • 您同时启动所有 Promise,尝试使用调试器运行它或放置控制台日志以检查发生了什么。您可以尝试在循环之外提取第一个调用,然后将 id 传递给循环中的其余调用。
  • 使用调试器可以按预期工作。以及所有使用 id 发送的下一个呼叫。但没有调试器不工作

标签: javascript angular typescript file-upload async-await


【解决方案1】:

[你可以使用这个特性:

public paramsArray = [
  {
    param1: '1',
    param2:  2
  },
  {
    param1: '3',
    param2:  4
  }
]

public subject: BehaviorSubject<any> = new BehaviorSubject<null>;

construnctor() {
  this.subject.asObservable().subscribe((value) => {
    if (value) {
      this.http.uploadImage(value).subscribe((res) => {
        if (this.paramsArray.length) {
          this.subject.next(paramsArray.splice(0, 1)[0]);
        }
      });
    }
  });
}

startUploading() {
  this.subject.next(this.paramsArray.splice(0, 1)[0]);
}

从paramsArray的索引0开始,依次上传。

【讨论】:

    【解决方案2】:

    我想对于要上传的第一张照片,您有一个 postId 存储在 this.postId 变量中。我们将使用那个来上传第一张照片,然后引入第二个变量来保存上传方法返回的post_id

    我们使用Observable 而不是Promise,因为众所周知,无论何时实例化它们,promise 都会被执行,这不是我们想要的。我们还使用concat 来确保所有文件都将被一一上传。

    private photoPostId: number | null = null;
    
    dropped(files: NgxFileDropEntry[]) {
      this.files = files;
    
      const tasks = files.map((droppedFile) => {
        return new Observable<number>((subscriber) => {
          if (droppedFile.fileEntry.isFile) {
            const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
            fileEntry.file(async (file: File) => {
              // Here you can access the real file
              console.log(droppedFile.relativePath, file);
    
              this.http
                .uploadImages(
                  file,
                  'UploadImage',
                  this.photoPostId ?? this.postId
                )
                .subscribe((res: any) => {
                  if (res.status == true) {
                    subscriber.next(res.data.post_id); // i want to send this ID in next request.
                  }
                });
            });
          } else {
            // It was a directory (empty directories are added, otherwise only files)
            const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry;
            console.log(droppedFile.relativePath, fileEntry);
          }
          subscriber.complete();
        });
      });
    
      concat(...tasks).subscribe((postId) => {
        this.photoPostId = postId;
      });
    }
    

    【讨论】:

    • 第一次 this.postId 是空字符串 '' 因为服务器针对第一个图像生成该 ID,并且在所有下一个图像中我发回了该 postId。
    • 我也用Observables尝试过这个,但结果相同。
    • 您尝试过我发布的解决方案吗?这对您有何帮助?
    • 不。它不工作。再次,它不等待先前的请求完成。
    • 请求是按顺序完成的,这就是concat 所做的。您是否尝试用此答案中的内容替换方法的内容?
    【解决方案3】:

    如果您正在寻找有关如何使用 Ngx-file-drop 获取文件的解决方案,这就是适合我的解决方案。

    伪代码

    • 获取droppedItems
    • 过滤文件
    • 创建可观察的流
    • 获取文件并执行所需的操作

    代码

    dropped(files: NgxFileDropEntry[]) {
        const droppedFileList = files.filter((droppedFile) => droppedFile.fileEntry.isFile);
    
        const subscription = new Subscription();
    
        subscription.add(
          from([droppedFileList])
            .pipe(
              switchMap((array) => {
                console.log('array', array);
                const result = array?.map((droppedFile) => {
                  const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
                  const promise = new Promise((res) => {
                    fileEntry.file((file) => res(file));
                  })
                  return from(promise);
                })
    
                return forkJoin(result);            
             })
            )
            .subscribe({
              next: (fileList) => console.log('fileList',fileList),
              error:(err)=> console.error(err)
              complete: () => subscription.unsubscribe()
            });
    }
    
    **For API calls**
    
    dropped(files: NgxFileDropEntry[]) {
        const droppedFileList = files.filter((droppedFile) => droppedFile.fileEntry.isFile);
    
        const subscription = new Subscription();
    
        subscription.add(
          from([droppedFileList])
            .pipe(
              switchMap((array) => {
                console.log('array', array);
                const result = array?.map((droppedFile) => {
                  const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
                  const promise = new Promise((res) => {
                    fileEntry.file((file) => res(file));
                  })
                  return from(promise);
                })
    
                return forkJoin(result);            
             }),
             switchMap((fileList) => apiFn(fileList))
            )
            .subscribe({
              next: (resp) => console.log('resp',resp),
              error:(err)=> console.error(err)
              complete: () => subscription.unsubscribe()
            });
    }
    
    apiFn(result){
      const calls = result.map(file => apiServiceFn(file));
      return forkJoin([...calls]);
    }
    

    您可以在此处了解有关 ForkJoin 的更多信息 - https://rxjs.dev/api/index/function/forkJoin

    【讨论】:

      猜你喜欢
      • 2019-05-17
      • 2019-10-16
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      相关资源
      最近更新 更多