【问题标题】:Angular: Declaring array of objects in TypescriptAngular:在 Typescript 中声明对象数组
【发布时间】:2019-12-02 06:37:54
【问题描述】:

我正在尝试在 Typescript 中声明一个对象数组。但是,我在检索对象时遇到错误。下面是我的代码。图片显示this.attachments的输出。

info: Info[];

if (this.attachments.length > 0) {
  this.previewInfo(this.attachments);
}

previewInfo(infos) {
  this.info = [];
  for (let i = 0; i < infos.length; i++) {
    let reader = new FileReader();
    reader.onload = (e: any) => {
      var temp = new Info;
      temp = {
        id: i,
        url: e.target.result,
        message: ""
      }
      this.info.push(temp);
    }
    reader.readAsDataURL(infos[i]);
  }
}

我得到的结果前面包含一个空数组,看起来像这样。

[]0: {id: 0, url: "test1", message: ""}
1: {id: 1, url: "test2", message: ""}
2: {id: 2, url: "test3", message: ""}

当我尝试使用

检索它们时,这会导致未定义
this.info[0]

如果我跳过第二行 this.info=[],我会收到一条错误提示

无法读取未定义的属性“0”

我是不是声明错了?如何按索引检索信息?

【问题讨论】:

  • 如果您共享更多代码会更好,但有一些基本错误,首先,您在没有this 的情况下声明信息,但您尝试在下一行使用this 访问info , this.info 将在您的上下文中创建新的 info 对象,我认为这是一些事件处理程序,现在如果您在删除第二个时尝试访问 this.info,您将收到错误,因为在 @987654335 上没有任何 info @上下文,阅读tylermcginnis.com/this-keyword-call-apply-bind-javascript & developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • @Harshkurra 我无法在打字稿中使用this 声明信息。
  • 显示你在哪里调用 previewInfo(infos)
  • @LuisRico 根据请求更新。
  • 最好在这里分享一个 MVCE stackblitz

标签: angular typescript asynchronous callback


【解决方案1】:

Akber Iqbal 的回答有效,但他们的解决方案不能保证文件与attachments 数组的顺序相同,所以

这里有一个解决方案,如果info 项与attachments 数组中的文件的顺序相同很重要。您正在寻找第一个项目,所以它可能很重要。我们可以使用 Promises 和 async/await:

async onFileSelected(event) {
  this.attachments = [];
  this.info = [];

  for (let index = 0; index < event.target.files.length; index++) {
    let file = event.target.files[index];
    this.attachments.push(file);
  }

  if (this.attachments.length > 0) {
    for (let i = 0; i < this.attachments.length; i++) {
      try {
        // wait that the file has been processed before moving on to next file
        let temp = await this.readFile(this.attachments[i], i);
        this.info.push(temp)

        if (this.attachments.length === this.info.length) {
          // here we have the first item after all files has been completed
          console.log(this.info[0])
        }
      } catch (err) {
        console.log(err);
      }
    }
  }
}

并在此处处理来自for-loop 的文件,方法是传递文件和索引并返回临时文件:

readFile(file, i) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();

    reader.onload = (e: any) => {
      let temp = {
        id: i,
        url: e.target.result,
        message: file.name, // for testing I put the file name as message
      }
      resolve(temp);
    };
    reader.readAsDataURL(file)
  })
}

演示:StackBlitz

【讨论】:

    【解决方案2】:

    问题在于异步调用;

    当您的循环完成并执行这两行时...到那时 reader.onload 还没有完成,因此 this.info.push(temp); 没有运行,当您运行这两行时,您会在控制台中看到一个空白下面:

    console.log(this.info);
    console.log(this.info[0]); //this is what i need
    

    我们需要做的是让循环结束,并在循环的最后一次迭代(i == infos.length - 1)中......我们在控制台上打印值并得到正确的结果;

    相关TS

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    
    export class AppComponent {
    
      //Variable declaration
      attachments = [];
      info = [];
    
      onFileSelected(event) {
        this.attachments = [];
        for (var index = 0; index < event.target.files.length; index++) {
          var file = event.target.files[index];
          this.attachments.push(file);
        }
        if (this.attachments.length > 0) {
          this.previewInfo(this.attachments);
          console.log('caller', this.attachments);
        }
      }
    
      previewInfo(infos) {
        this.info = [];
        if (infos) {
          for (let i = 0; i < infos.length; i++) {
            let reader = new FileReader();
            reader.onload = (e: any) => {
              let temp = {
                id: i,
                url: e.target.result,
                message: "",
              }
              //console.log(temp);
              if (i == infos.length - 1) {
                this.pusher(temp, true);
              } else {
                this.pusher(temp, false);
              }
              //this.info.push(temp, function(){ console.log('pushed'); } );
            }
            reader.readAsDataURL(infos[i]);
          }
          console.log('empty: ', this.info);
          console.log('empty: ', this.info[0]); //this is what i need
        }
      }
    
      pusher(tempFile, lastFile) {
        this.info.push(tempFile);
        if (lastFile == true) {
          console.log('Correct Filled: ', this.info.length);
          console.log('Correct Filled: ', this.info[0]); //this is what i need
        }
      }
    
    }
    

    完成working stackblitz here

    【讨论】:

      猜你喜欢
      • 2021-08-04
      • 2017-01-17
      • 1970-01-01
      • 2013-03-22
      • 2023-01-26
      • 2019-10-28
      • 2022-08-20
      • 2021-09-19
      • 2016-12-16
      相关资源
      最近更新 更多