我正在尝试使用 switchmap 在 ngrx 效果中执行多个 API 调用
该操作需要输入要上传的文件数组,并且 api 支持一次一个文件
我的效果如下
uploadFiles$ = createEffect(() =>
this.actions$.pipe(
ofType(uploadFiles),
switchMap(({id, files}) => {
const uploadApiList = []
for(let i =0 ; I<files ; i++) {
uploadApiList.push(this.apiService.uploadFile(id, files[i]));
}
return uploadApiList;
}),
tap(result=> console.log(result ),
tap(res=> {return uploadFilesSuccess({response: res})}),
catchError(error => of(uploadFailure({ errorResponse: error })))
),
{ dispatch: false }
);
服务方式
public uploadFile(id: string, file: File): Observable<any> {
console.log('***************')
const formData: FormData = new FormData();
formData.append('file', file);
return new Observable(observer => {
this.store.dispatch(showLoadingMask());
this.httpClient.post<any>(`${this.baseUrl}/${id}/upload-files`, formData).subscribe(
(response: HttpResponse<any>) => {
console.log(formData)
observer.next(response?.body);
observer.complete();
this.store.dispatch(hideLoadingMask());
},
error => {
this.logService.error('[UNEXPECTED_RESPONSE]', error);
observer.error(error);
observer.complete();
this.store.dispatch(hideLoadingMask());
}
);
});
}
但是 api 永远不会被调用,结果会打印为 Observables 数组,我也可以看到我调用的方法,但 http 调用没有发生
我不知道我做错了什么?
我对
ngrx
没有太多经验,但我们需要对可观察数组(forkJoin
)执行 uploadApiList
来获取内部值,也不需要在 uploadFile
内进行订阅
,我们可以只使用 map
和 catchError
!
另外,
tap
不接受返回值(uploadFilesSuccess({response: res})
),所以我将其更改为接受返回值的map
!
uploadFiles$ = createEffect(() =>
this.actions$.pipe(
ofType(uploadFiles),
switchMap(({id, files}) => {
this.store.dispatch(showLoadingMask());
const uploadApiList = [];
files.forEach((file: any) => {
uploadApiList.push(this.apiService.uploadFile(id, file));
});
return forkJoin(uploadApiList);
}),
tap(result=> {
this.store.dispatch(hideLoadingMask());
console.log(result);
}),
map(res => {
return uploadFilesSuccess({response: res});
}),
catchError(error => {
this.store.dispatch(hideLoadingMask());
return of(uploadFailure({ errorResponse: error }))
}),
),
{ dispatch: false }
);
服务:
public uploadFile(id: string, file: File): Observable<any> {
console.log('***************')
const formData: FormData = new FormData();
formData.append('file', file);
return this.httpClient.post<any>(`${this.baseUrl}/${id}/upload-files`, formData).pipe(
map((response: HttpResponse<any>) => {
return response?.body;
},
catchError(error => {
this.logService.error('[UNEXPECTED_RESPONSE]', error);
throw error;
}),
);
}