Angular 2& Vanilla JS:在进行http调用之前等待图像加载

时间:2017-07-25 12:19:39

标签: angular rxjs observable

我正在使用服务在服务器上上传图片。这是:

addPictures(files: File[], folder: string): Observable<Parse.Object[]> {
  let hasError = false;
  for (let file of files) {
    let [type, ext] = file.type.split('/');
    if (type.toLowerCase() !== 'image' || !environment.imgExts.includes(ext.toLowerCase())) { hasError = true; }
  }
  if (hasError) { return Observable.throw('Invalid extension detected'); }

  let observables: Observable<Parse.Object>[] = [];

  for (let file of files) {
    // Get its size
    let img = new Image();
    img.onload = () => {
      // Create the Parse document
      let parseImg = { url: '', type: file.type, width: img.width, height: img.height };
      // Upload it on Amazon and add it to DB
      observables.push(this.addPicture(parseImg, file, folder));
      console.log('pushing to array');
    }
    img.src = window.URL.createObjectURL(file);
  }
  console.log('forkjoin');
  return Observable.forkJoin(observables);
}

所有功能都很棒。我面临的问题是,当我使用img.onload时,forkJoin不会在开始之前等待它。我想要的是等待所有图像加载,然后触发thr forkJoin发送所有图像

我已经尝试了一个条件(当最后一项被推到数组时,触发forkJoin),带有一个主题,但问题是我的组件返回Cannot read property 'subscribe' of undefined行的错误。

编辑这是我的来自事件的代码:

addPictures(files: File[], folder: string): Observable<Parse.Object[]> {
  let hasError = false;
  for (let file of files) {
    let [type, ext] = file.type.split('/');
    if (type.toLowerCase() !== 'image' || !environment.imgExts.includes(ext.toLowerCase())) { hasError = true; }
  }
  if (hasError) { return Observable.throw('Invalid extension detected'); }

  let observables: Observable<Parse.Object>[] = [];

  for (let file of files) {
    // Get its size
    let img = this.fromImgEvent(file, window.URL.createObjectURL(file), folder);
    observables.push(img);
  }
  console.log('forkjoin');
  return Observable.forkJoin(observables);
}

fromImgEvent(file: File, url: string, folder: string) {
  return Observable.create(observer => {
    let img = new Image();
    img.onload = () => {
      // Create the Parse document
      let parseImg = { url: '', type: file.type, width: img.width, height: img.height };
      // Upload it on Amazon and add it to DB
      observer.next(this.addPicture(parseImg, file, folder));
      observer.complete();
    }
    img.src = url;
  });
}

1 个答案:

答案 0 :(得分:0)

您可以使用例如Observable.fromEvent或自己创建一个Observable来加载图像,如下所示:

addPictures(files: File[], folder: string): Observable<Parse.Object[]> {
  let hasError = false;
  let data$ = files.map(file => {
    let [type, ext] = file.type.split('/');
    if (type.toLowerCase() !== 'image' || !environment.imgExts.includes(ext.toLowerCase())) { 
      hasError = true;
    }
    return Observable.create(observer => {
        let image = new Image();
        image.src = window.URL.createObjectURL(file);
        image.onload = (e) => {
            let parsedImage = { url: '', type: file.type, width: image.width, height: image.height };
            observer.next({ parsedImage, file });
            observer.complete();
        };
    });
  };
  if (hasError) { 
    return Observable.throw('Invalid extension detected');
  }
  return Observable
    .forkJoin(data$)
    .toArray()
    .switchMap(([parsedData]) => {
        return Observable.forkJoin(
            parsedData.map(data => {
                return this.addPicture(data.parsedImage, data.file, folder)
            })
        );
    });
}