我有以下打字稿代码。
我试图使packageFiles方法成为可观察的,所以我可以等到完成后再继续。但是有什么不对吗?
packageFiles(): Observable<any> {
var filesToSend = [];
//Loop through files
this.files.forEach(f => {
var reader = new FileReader();
reader.onload = (e) => {
//
var fileForUpload = new FileForUpload();
var encodedString = window.btoa(<string>reader.result);
fileForUpload.FileValue = encodedString;
fileForUpload.FileName = f.name;
fileForUpload.FileType = f.type;
//
filesToSend.push(fileForUpload);
console.log(filesToSend);
};
reader.readAsDataURL(f);
});
return of(filesToSend);
}
此方法随后将其调用:
uploadFiles() {
var response = this.packageFiles()
.subscribe(
data => {
console.log("data");
console.log(data);
},
error => {
}
);
}
答案 0 :(得分:0)
在调用filesToSend
时,您将插入reader.onload
,而在遍历文件时不会发生这种情况。自然,在通过filesToSend
构造可观察对象时,您的of
是一个空数组。调用订阅将直接导致主题发出空数组。
相反,您应该创建一个主题,每次加载完成后都调用next()
。
答案 1 :(得分:0)
您正在此处同步返回一个可观察到的空数组,这不是您想要执行的操作。您需要确保首先收集数据,然后在可观察的位置发射(of
立即发射然后完成)。
让我们假设您只有一个file
。在这种情况下,最接近您的代码的地方将使用Subject
:
packageFiles(): Observable<FileForUpload> {
const result$ = new Subject<FileForUpload>();
const reader = new FileReader();
reader.onload = () => {
const fileForUpload = new FileForUpload();
// … do your stuff …
result$.next(fileForUpload);
result$.complete();
};
// …
return result$;
}
但是,这将返回一个热的可观测值,最好在这里返回一个冷的可观测值:
packageFiles(): Observable<FileForUpload> {
return Observable.create(observer => {
const reader = new FileReader();
reader.onload = () => {
const fileForUpload = new FileForUpload();
// … do your stuff …
observer.next(fileForUpload);
observer.complete();
};
// …
});
}
现在,您只需要将其概括为多个文件即可。让我们将其重命名为packageFile
并将文件作为输入传递:
packageFile(file: File): Observable<FileForUpload> {
// …
}
然后我们可以将实际函数编写为
packageFiles(): Observable<FileForUpload[]> {
return forkJoin(...this.files.map(file => this.packageFile(file)));
}
…现在可以通过致电使用
this.packageFiles().subscribe(filesToUpload => { /* … */ });