загрузка асинхронных входящих изображений в хранилище Firebase и ожидание возвращения всех URL-адресов - PullRequest
0 голосов
/ 26 июня 2019

так что я угловое приложение, которое позволяет вам загружать некоторые вещи в облачное хранилище. скажем, название, описание и некоторые изображения. Я храню изображения в хранилище Firebase, а затем добавляю URL загрузки для FireBase, а также. Я создаю метод, который принимает массив файлов, обрезает изображения до более удобного размера и затем загружает эти файлы в хранилище firebase:

  uploadImages(images, title) {
    const urls: string[] = [];
    this.ng2ImgToolsService.resize(images, 700, 400).subscribe(result => {
      const uploadImage = new File([result], result.name);

      const path = `${title}/${Date.now()}_${uploadImage.name}`;
      const ref = this.storage.ref(path);
      const task = this.storage.upload(path, uploadImage);

      task.snapshotChanges().pipe(tap(), finalize(async () => {
        const url = await ref.getDownloadURL().toPromise;
        urls.push(url);
      }));  

    }, error => {
      console.log('resize failed, returning original images: ' + error)
    });

    return urls;
  }

это, очевидно, не работает. Я также попытался обернуть все в обещание, чтобы я мог сделать;

const urls = await this.uploadImages(...);

но в этот момент у меня есть наблюдаемые в наблюдаемых в обещании наблюдаемых, и я должен признать, что у меня над головой. времена, когда я работал с асинхронными задачами, они были более прямыми.

Я провожу еще пару дней, читая RxJ, но боюсь, что не могу понять это самостоятельно.

Подводя итог, эта функция должна возвращать массив URL-адресов, мне нужно иметь возможность ждать этого массива, поэтому в основном ждите загрузки всего в firestore, пока у меня не появятся URL-адреса загрузки.

редактировать Хорошо, после игры с ответом dockleryxk, я все еще сталкиваюсь с некоторыми проблемами. Прежде всего, функция «ng2ImgToolsService.resize (images, 700, 400)» принимает массив изображений и возвращает обещание, которое будет проходить через каждое обрезанное изображение, как только это будет сделано, на месте всех их сразу , Поэтому, если я попытаюсь обернуть это в обещание и разрешить вывод этой наблюдаемой, он вернет только одно изображение (в зависимости от того, что будет обрезано первым). Таким образом, я должен был бы ждать, пока наблюдаемое будет сделано, испуская данные? Это возможно?

Во-вторых, если бы я действительно все разделил, чтобы, получив массив обрезанных изображений, я поместил эти изображения в новую функцию. В этой функции я должен был бы перебрать этот массив и загрузить их один за другим.

 uploadImages2(images, title) {
    const observables = [];

    for (let image of images) {
      const path = `${title}/${Date.now()}_${image.name}`;
      const ref = this.storage.ref(path);
      const task = this.storage.upload(path, image);

      task.snapshotChanges().pipe(tap(), finalize(async () => {
        const url =  ref.getDownloadURL();
        observables.push(url);
      }));
    }

    return new Promise((resolve, reject) => {
      Observable.combineLatest(observables).subscribe(
        responses => {
          resolve(responses);
        },
        error => {
          console.log('error:', error);
          reject(error);
        }
      );
    });
  }

это правильно загружает изображения, но не возвращает загруженный массив URL. оно в основном замирает где-то в обещании

Ответы [ 2 ]

0 голосов
/ 29 июня 2019

Хорошо, я все понял. Огромное спасибо dockleryxk за общее рабочее решение. Разделив мою функцию и в основном выполнив тактику dockleryxk, дважды получилось:

Функция изменения размера входящих изображений:

resizeImages(images: File[], width: number, height: number) {

    /*
    this function takes in an array of images, a width and a height.
    if the array contains 'png' or 'jpg' files. it will scale down the images to either the width or the height given.
    if the array contains other image files it will just return them.
    */

    const toResize: File[] = [];
    const resized: File[] = [];

    for (const file of images) {
      if (this.getFileExtension(file) === 'png' || this.getFileExtension(file) === 'jpg') {
        toResize.push(file);
      } else {
        resized.push(file);
      }
    }

    return new Promise((resolve, reject) => {
      if (toResize.length > 0) {
        this.ng2ImgToolsService.resize(toResize, width, height).subscribe(response => {
          resized.push(this.blobToFile(response, response.name));

          if (resized.length === images.length) {
            resolve(resized);
          }
        }, error => {
          console.log('error:', error);
          reject(error);
        });
      } else {
        resolve(resized);
      }
    });
  }

функция загрузки этих изображений:

  uploadImages(images: File[], title: string) {
    return new Promise((resolve, reject) => {
      const urls: string[] = [];
      for (const file of images) {
        const path = `${title}/${Date.now()}_${file.name}`;
        const ref = this.storage.ref(path);
        const task = this.storage.upload(path, file);

        task.snapshotChanges().pipe(
          finalize(() => {
            ref.getDownloadURL().subscribe(url => {
              urls.push(url);

              if (images.length === urls.length) {
                resolve(urls);
              }
            });
          })
        ).subscribe();
      }
    });
  }

и затем использовать их в своем коде:

const imgs: any = await this.resizeImages(data.images, 700, 400);
console.log(imgs);
const urls: any = await this.uploadImages(imgs, data.title);
console.log(urls);

Я могу сказать, что это не лучшее решение, я жду неоправданно долго, и это может быть ускорено. Так что, если у кого-то есть лучшее решение, я бы с удовольствием его услышал. но это работает!

0 голосов
/ 26 июня 2019

Поскольку вам более комфортно с обещаниями, вы можете сделать что-то вроде создания массива ваших наблюдаемых и затем объединить их.

const observables = [
  ...
];

return new Promise((resolve, reject) => {
  Observable.combineLatest(observables).subscribe(
    responses => {
      // responses array will be in the same order as requests
      console.log('responses:', responses);
      resolve(responses);
    },
    error => {
      console.log('error:', error);
      reject(error);
    }
  );
});

РЕДАКТИРОВАТЬ: я не понял, как пакет работает точно, попробуйтекак то так:

uploadImages(images, title) {
  const urls: string[] = [];
  return new Promise((resolve, reject) => {
    this.ng2ImgToolsService.resize(images, 700, 400).subscribe(result => {
      const uploadImage = new File([result], result.name);

      const path = `${ title }/${ Date.now() }_${ uploadImage.name }`;
      const ref = this.storage.ref(path);
      const task = this.storage.upload(path, uploadImage);

      task.snapshotChanges().pipe(tap(), finalize(async () => {
        const url = await ref.getDownloadURL().toPromise();
        urls.push(url);
        // in this case, all images should be done
        if (urls.length === images.length) {
          resolve(urls);
        }
      }));

    }, error => {
      console.log('resize failed, returning original images: ' + error);
      reject(error);
    });
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...