在 for 循环中使用 Angular HttpClient
Using Angular HttpClient inside for loop
我对 Angular 的 HttpClient 有一些问题:
因此,应用程序逻辑如下所示:
component.ts:
我需要从服务调用 createNewVideoUploadId() 来获取上传视频的 ID。比我需要将文件发送到服务方法:
uploadVideoToApi() {
this.lessonService.createNewVideoUploadId()
.subscribe(res => {
this.lessonService.uploadNewVideo(this.videoToUpload, res['X-Upload-File-ID'])
})
}
lessonService 看起来像:
createNewVideoUploadId() {
return this.http.get<string>(`${environment.apiUrl}/upload/id`)
}
上传新视频:
uploadNewVideo(video: File, id: string) {
const chunkSize = 10 * 1024 ** 2;
const count = Math.ceil(video.size / chunkSize);
let calls = []
for (let i = 0; i < count; i++) {
let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);
let fd = new FormData();
fd.append('file', chunk);
fd.append('file_name', video.name);
fd.append('file_size', video.size.toString());
fd.append('chunk_size', chunkSize.toString());
fd.append('chunk_number', i.toString());
fd.append('chunks_count', count.toString());
return this.http.post(`${environment.apiUrl}/upload/${id}`, fd)
}
} // uploadNewVideo()
因此,for 循环在第一次迭代中停止,因为 return
我需要从component.ts
开始一个一个地执行每个for循环迭代
因此,我需要订阅 uploadNewVideo,并获得回复。但是我不能 return 循环中的任何东西。
只需将 http-post 流存储在一个数组中并连接它们:
uploadNewVideo(video: File, id: string) {
const chunkSize = 10 * 1024 ** 2;
const count = Math.ceil(video.size / chunkSize);
let calls = []
let httpCalls = [];
for (let i = 0; i < count; i++) {
let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);
let fd = new FormData();
fd.append('file', chunk);
fd.append('file_name', video.name);
fd.append('file_size', video.size.toString());
fd.append('chunk_size', chunkSize.toString());
fd.append('chunk_number', i.toString());
fd.append('chunks_count', count.toString());
httpCalls.push(this.http.post(`${environment.apiUrl}/upload/${id}`, fd));
}
return concat(httpCalls)
}
你可以使用 RxJS forkJoin()
方法。尝试以下
uploadNewVideo(video: File, id: string) {
const chunkSize = 10 * 1024 ** 2;
const count = Math.ceil(video.size / chunkSize);
let calls = []
for (let i = 0; i < count; i++) {
let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);
let fd = new FormData();
fd.append('file', chunk);
fd.append('file_name', video.name);
fd.append('file_size', video.size.toString());
fd.append('chunk_size', chunkSize.toString());
fd.append('chunk_number', i.toString());
fd.append('chunks_count', count.toString());
calls.push(this.http.post(`${environment.apiUrl}/upload/${id}`, fd).pipe(retry(3))) // <-- retry 3x in case of error
}
return forkJoin(calls); // <-- use `forkJoin` here
}
现在您可以订阅触发调用的函数了
uploadVideoToApi() {
this.lessonService.createNewVideoUploadId().pipe(
switchMap(res => this.lessonService.uploadNewVideo(this.videoToUpload, res['X-Upload-File-ID'])),
catchError(error => of(error))
).subscribe(
response => {
// handle response
},
error => {
// handle error
}
);
}
我对 Angular 的 HttpClient 有一些问题:
因此,应用程序逻辑如下所示: component.ts:
我需要从服务调用 createNewVideoUploadId() 来获取上传视频的 ID。比我需要将文件发送到服务方法:
uploadVideoToApi() {
this.lessonService.createNewVideoUploadId()
.subscribe(res => {
this.lessonService.uploadNewVideo(this.videoToUpload, res['X-Upload-File-ID'])
})
}
lessonService 看起来像:
createNewVideoUploadId() {
return this.http.get<string>(`${environment.apiUrl}/upload/id`)
}
上传新视频:
uploadNewVideo(video: File, id: string) {
const chunkSize = 10 * 1024 ** 2;
const count = Math.ceil(video.size / chunkSize);
let calls = []
for (let i = 0; i < count; i++) {
let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);
let fd = new FormData();
fd.append('file', chunk);
fd.append('file_name', video.name);
fd.append('file_size', video.size.toString());
fd.append('chunk_size', chunkSize.toString());
fd.append('chunk_number', i.toString());
fd.append('chunks_count', count.toString());
return this.http.post(`${environment.apiUrl}/upload/${id}`, fd)
}
} // uploadNewVideo()
因此,for 循环在第一次迭代中停止,因为 return
我需要从component.ts
开始一个一个地执行每个for循环迭代因此,我需要订阅 uploadNewVideo,并获得回复。但是我不能 return 循环中的任何东西。
只需将 http-post 流存储在一个数组中并连接它们:
uploadNewVideo(video: File, id: string) {
const chunkSize = 10 * 1024 ** 2;
const count = Math.ceil(video.size / chunkSize);
let calls = []
let httpCalls = [];
for (let i = 0; i < count; i++) {
let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);
let fd = new FormData();
fd.append('file', chunk);
fd.append('file_name', video.name);
fd.append('file_size', video.size.toString());
fd.append('chunk_size', chunkSize.toString());
fd.append('chunk_number', i.toString());
fd.append('chunks_count', count.toString());
httpCalls.push(this.http.post(`${environment.apiUrl}/upload/${id}`, fd));
}
return concat(httpCalls)
}
你可以使用 RxJS forkJoin()
方法。尝试以下
uploadNewVideo(video: File, id: string) {
const chunkSize = 10 * 1024 ** 2;
const count = Math.ceil(video.size / chunkSize);
let calls = []
for (let i = 0; i < count; i++) {
let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);
let fd = new FormData();
fd.append('file', chunk);
fd.append('file_name', video.name);
fd.append('file_size', video.size.toString());
fd.append('chunk_size', chunkSize.toString());
fd.append('chunk_number', i.toString());
fd.append('chunks_count', count.toString());
calls.push(this.http.post(`${environment.apiUrl}/upload/${id}`, fd).pipe(retry(3))) // <-- retry 3x in case of error
}
return forkJoin(calls); // <-- use `forkJoin` here
}
现在您可以订阅触发调用的函数了
uploadVideoToApi() {
this.lessonService.createNewVideoUploadId().pipe(
switchMap(res => this.lessonService.uploadNewVideo(this.videoToUpload, res['X-Upload-File-ID'])),
catchError(error => of(error))
).subscribe(
response => {
// handle response
},
error => {
// handle error
}
);
}