ngFor над объектом, заполненным из promise в Angular 2

#javascript #angular #blob #jszip

#javascript #angular #большой двоичный объект #jszip

Вопрос:

Я анализирую zip-файл с изображениями, на которые я хочу ссылаться с помощью blobURL в filesFromZip объекте, и выполняю итерацию по нему с помощью ngFor, чтобы отобразить изображения на странице.

Это выглядит так

 filesFromZip = {};
let zip = new JSZip();

zip.loadAsync(zipfileFromInput)
  .then(function (zip) {
    for (let file in zip.files) {

    let fileInZip = zip.files[file];

    zip.file(fileInZip.name)
      .async("arraybuffer")
      .then(function (content) {
        let buffer = new Uint8Array(content);
        let blob = new Blob([buffer.buffer]);

        // here is where I want to push this object into the filesFromZip object somehow....
        return {
          fileName: fileInZip.name,
          blobURL: URL.createObjectURL(blob)
        };
    });
   }
  });
  

в шаблоне:

 <md-card *ngFor="let file of filesFromZip">
  <h3 md-line>{{file.fileName}}</h3>
  <img src="{{file.blobURL}}">
</md-card>
  

Как я могу получить данные из promise в filesFromZip ?

Я пытался просто вставить его в filesFromZip , но это выдает мне эту ошибку:

error_handler.js:47 ИСКЛЮЧЕНИЕ: Неперехваченный (в promise): ошибка типа: не удается прочитать свойство ‘async’, равное нулю

Я действительно борюсь с асинхронностью и Angular 2. Кто-нибудь, кто может направить меня в правильном направлении?

Ответ №1:

Во-первых, вы не можете выполнять итерацию по простому объекту с *ngFor директивой, поэтому filesFromZip должен быть массив.

 this.filesFromZip = [];
zip.loadAsync(zipfileFromInput)
  .then((zip)=> {
    for (let file in zip.files) {
      let fileInZip = zip.files[file];
      zip.file(fileInZip.name)
        .async("arraybuffer")
        .then((content)=> {
          let buffer = new Uint8Array(content);
          let blob = new Blob([buffer.buffer]);
          // here is where I want to push this object into the filesFromZip object somehow....
          this.filesFromZip.push({
            fileName: fileInZip.name,
            blobURL: URL.createObjectURL(blob)
          });
      });
   }
  });
  

или вы можете использовать Promise.all(), который создаст promise из итерации Promise, а затем использует асинхронный канал :

javascript :

 this.filesFromZip = Promise.all(
  zip.loadAsync(zipfileFromInput)
    .then((zip)=> {
      let out=[];
      for (let file in zip.files) {
        let fileInZip = zip.files[file];
        out.push(zip.file(fileInZip.name)
          .async("arraybuffer")
          .then((content)=> {
            let buffer = new Uint8Array(content);
            let blob = new Blob([buffer.buffer]);
            // here is where I want to push this object into the filesFromZip object somehow....
            this.filesFromZip.push({
              fileName: fileInZip.name,
              blobURL: URL.createObjectURL(blob)
            });
        }));
    }
    return out;
    });
)
  

шаблон :

 <md-card *ngFor="let file of filesFromZip|async">
  <h3 md-line>{{file.fileName}}</h3>
  <img src="{{file.blobURL}}">
</md-card>
  

Однако ваша главная проблема здесь, похоже, заключается в том, что zip.file(fileInZip.name) возвращается null

Комментарии:

1. Чтобы использовать асинхронный канал, не должен ли filesFromZip возвращать promise, а не так, как я сейчас пытаюсь вернуть объект?

2. Просто новый пустой объект, в который я пытался вставить результат из promise

3. вы имеете в виду этот результат: return { fileName: fileInZip.name, blobURL: URL.createObjectURL(blob) }; ? Потому что, поскольку это возвращается обещанием, оно станет обещанием…

4. Да, я пытался вставить этот объект для каждого файла в filesFromZip вместо его возврата, но он выдал ошибку. Но теперь возвращаемый объект живет только в promise, и я не знаю, как получить его в filesFromZip

5. Откуда берется эта filesFromZip переменная !!!??? Пожалуйста, отредактируйте свой вопрос со всей необходимой информацией…