在for循环中可观察?
Observable in for loop?
我想在 for 循环中调用可观察的 REST 服务。它 returns base64 编码的 csv 文件。我想解码它并将它连接成一个字符串并 return 它。之后,我尝试订阅该方法并单击 DOM 进行下载。我得到只有 "\r\n"
的空字符串。为什么在 returning 之前不等待 REST return 文件?
downloadFilesAndConcatenate(): Observable<any> {
let concatenatedFileDecoded: string = '\r\n';
for (let i = 0; i < this.fileIDs.length; i++) {
this.restService.getFile(this.fileIDs[i]).subscribe(response => {
this.fileResultSet = response;
this.message = response.message;
this.file = this.fileResultSet.result;
let fileCSVbase64 = this.file.fileBytes
let fileCSVDecoded = atob(fileCSVbase64);
concatenatedFileDecoded += fileCSVDecoded;
},
error => {
this.message = error.error.message;
});
return new Observable( observer => {
observer.next(concatenatedFileDecoded)
observer.complete();
});
}
}
然后我订阅了它:
download() {
if (this.dateEnd !== null && typeof this.dateEnd !== "undefined") {
debugger;
this.downloadFilesAndConcatenate() // Multiple files
.subscribe(
(result) => {
debugger;
const link = document.createElement( 'a' );
link.style.display = 'none';
document.body.appendChild( link );
const blob = new Blob([result], {type: 'text/csv'});
const objectURL = URL.createObjectURL(blob);
link.href = objectURL;
link.href = URL.createObjectURL(blob);
link.download = this.file.name;
link.click();
},
(err) => {
console.error(err);
},
() => console.log("download observable complete")
);
} else {
this.downloadFile(); // Only one file
}
}
因为是异步代码。预计同步代码将比异步代码更早执行。
正确的代码应该是这样的
downloadFilesAndConcatenate(): Observable<string> {
return forkJoin(this.fileIDs.map(id => this.restService.getFile(id))).pipe(
map(responses => '\r\n'+responses.map(r => atob(r.result.fileBytes)).join(''))
catchError(e => this.message = e.error.message)
);
}
我想在 for 循环中调用可观察的 REST 服务。它 returns base64 编码的 csv 文件。我想解码它并将它连接成一个字符串并 return 它。之后,我尝试订阅该方法并单击 DOM 进行下载。我得到只有 "\r\n"
的空字符串。为什么在 returning 之前不等待 REST return 文件?
downloadFilesAndConcatenate(): Observable<any> {
let concatenatedFileDecoded: string = '\r\n';
for (let i = 0; i < this.fileIDs.length; i++) {
this.restService.getFile(this.fileIDs[i]).subscribe(response => {
this.fileResultSet = response;
this.message = response.message;
this.file = this.fileResultSet.result;
let fileCSVbase64 = this.file.fileBytes
let fileCSVDecoded = atob(fileCSVbase64);
concatenatedFileDecoded += fileCSVDecoded;
},
error => {
this.message = error.error.message;
});
return new Observable( observer => {
observer.next(concatenatedFileDecoded)
observer.complete();
});
}
}
然后我订阅了它:
download() {
if (this.dateEnd !== null && typeof this.dateEnd !== "undefined") {
debugger;
this.downloadFilesAndConcatenate() // Multiple files
.subscribe(
(result) => {
debugger;
const link = document.createElement( 'a' );
link.style.display = 'none';
document.body.appendChild( link );
const blob = new Blob([result], {type: 'text/csv'});
const objectURL = URL.createObjectURL(blob);
link.href = objectURL;
link.href = URL.createObjectURL(blob);
link.download = this.file.name;
link.click();
},
(err) => {
console.error(err);
},
() => console.log("download observable complete")
);
} else {
this.downloadFile(); // Only one file
}
}
因为是异步代码。预计同步代码将比异步代码更早执行。 正确的代码应该是这样的
downloadFilesAndConcatenate(): Observable<string> {
return forkJoin(this.fileIDs.map(id => this.restService.getFile(id))).pipe(
map(responses => '\r\n'+responses.map(r => atob(r.result.fileBytes)).join(''))
catchError(e => this.message = e.error.message)
);
}