我正在尝试在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”
我错误地声明了吗?如何按索引检索信息?
答案 0 :(得分:0)
问题在于异步调用;
当循环结束并且执行了这两行时...那时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
}
}
}
答案 1 :(得分:0)
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
循环中处理文件:
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