如何将FileSystemFileEntry.file包装到返回Observable的函数中?

时间:2018-11-07 04:26:30

标签: javascript angular observable

我正在尝试从放置的文件夹中递归读取文件。

onDrop(event) {
  event.preventDefault();
  this.folderData = [];
  this.filesData = [];

    const items = event.dataTransfer.items;
    for (let i = 0; i < items.length; i++) {
      const item = items[i].webkitGetAsEntry();
      if (item) {
        this.scanFiles(item, this.folderData);
      }
    }
    // send out data
    // this.dropped.emit({ folderData: this.folderData, filesData: this.filesData });
}

private scanFiles(item, container: Array<any>) {
  const nodeData = {
    name: item.name,
    isDirectory: item.isDirectory,
    item: item,
    children: []
  };

  container.push(nodeData);
  if (item.isDirectory) {
    const directoryReader = item.createReader();
    directoryReader.readEntries(entries => {
      if (entries) {
        entries.forEach(entry => this.scanFiles(entry, nodeData.children));
      }
    });
  } else if (item.isFile) {
    // How to return an Observable array here? 
    item.file(file => {
      file.fullPath = item.fullPath;
      this.filesData.push(file);
    });
  }

}

根据MDN,FileSystemFileEntry.file在其回调中返回结果。 https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry/file

因此,在onDrop发送结果之前,它必须等待,直到完成所有FileSystemFileEntry.file回调为止。

我想使用Observable.forkJoin实现这一点。但是在此之前,如何将FileSystemFileEntry.file包装到一个返回Observable的函数中?

1 个答案:

答案 0 :(得分:1)

事实证明,单个forkJoin无法解决问题。我终于通过递归forkJoin完成了此操作。

onDrop(event) {
  event.preventDefault();
  this.folderData = [];
  this.filesData = [];

  const items = event.dataTransfer.items;
  const obs = [];
  for (let i = 0; i < items.length; i++) {
    const item = items[i].webkitGetAsEntry();
    if (item) {
      obs.push(new Observable<any>(observer => this.scanFiles(item, this.folderData, observer)));
    }
  }

  forkJoin(obs).subscribe(e => {
    this.dropped.emit({ folderData: this.folderData, filesData: this.filesData });
  });
}

private scanFiles(item, container: Array<any>, observer: Subscriber<any>) {
const nodeData = {
  name: item.name,
  isDirectory: item.isDirectory,
  item: item,
  children: []
};

container.push(nodeData);
if (item.isDirectory) {
  const directoryReader = item.createReader();
  directoryReader.readEntries(entries => {
    if (entries) {
      if (entries.length === 0) {
        observer.next();
        observer.complete();
      } else {
        const subObs = entries.map(entry => new Observable<any>(innerObserver =>
          this.scanFiles(entry, nodeData.children, innerObserver)));
        forkJoin(subObs).subscribe(e => {
          observer.next();
          observer.complete();
        });
      }
    } else {
      observer.next();
      observer.complete();
    }
  });
} else if (item.isFile) {
  item.file(file => {
      file.fullPath = item.fullPath;
      this.filesData.push(file);
      observer.next();
      observer.complete();
  });
}

}

要进行更详细的检查,https://github.com/ft115637850/ngx-folder-uploader