如何使用Angular RxJS按顺序请求并将响应分配到对应列表?
按顺序发起HTTP请求并将响应分配到对应列表的解决方案
你需要按固定顺序发起多个HTTP请求,每个请求的响应要渲染到独立的HTML列表中,但当前使用concatMap只能逐个获取响应对象,无法区分每个响应对应的目标列表。以下是两种可行的解决方案:
方法一:为请求绑定目标标识
给每个请求包装一个包含目标列表标识的对象,在获取响应时直接根据标识赋值到对应列表:
步骤1:修改请求数组,添加目标标识
const reqWithTargets = [ { request: this.domainService.getDomain(filterNG).pipe( map(resp => resp.data), finalize(() => this.loadingNG = false) ), target: 'listNG' }, { request: this.domainService.getDomain(filterCodAML).pipe( map(resp => resp.data), finalize(() => this.loadingCodAML = false) ), target: 'listCodAML' }, { request: this.domainService.getDomain(filterTipoRating).pipe( map(resp => { resp.data.unshift({code: this.TIPO_RATING_ALL, description: this.translate.instant('tutti')}); return resp.data; }), finalize(() => this.loadingTipiRating = false) ), target: 'listTipoRating' }, { request: this.komodoService.listProvince$().pipe( finalize(() => this.loadingProvince = false) ), target: 'listProvince' }, { request: this.domainService.getDomain(filterGRA).pipe( map(resp => resp.data), finalize(() => this.loadingGRA = false) ), target: 'listGRA' }, { request: this.anagraficaService.getListaFiliali({filter: {all: false}}).pipe( map(resp => resp.data), finalize(() => this.loadingFiliali = false) ), target: 'listFiliali' } ];
步骤2:订阅时根据标识分配响应
from(reqWithTargets).pipe( concatMap(item => item.request.pipe( map(resp => ({ data: resp, target: item.target })) )) ).subscribe(({ data, target }) => { switch(target) { case 'listNG': this.listNG = data; break; case 'listCodAML': this.listCodAML = data; break; case 'listTipoRating': this.listTipoRating = data; break; case 'listProvince': this.listProvince = data; break; case 'listGRA': this.listGRA = data; break; case 'listFiliali': this.listFiliali = data; break; } });
步骤3:HTML中渲染对应列表
<!-- NG列表 --> <div *ngIf="listNG.length"> <h3>NG 列表</h3> <ul> <li *ngFor="let item of listNG">{{ item.description }}</li> </ul> </div> <!-- CodAML列表 --> <div *ngIf="listCodAML.length"> <h3>CodAML 列表</h3> <ul> <li *ngFor="let item of listCodAML">{{ item.description }}</li> </ul> </div> <!-- 其他列表依此类推 -->
方法二:利用请求数组索引匹配列表
由于请求数组的顺序是固定的,每个请求的索引对应目标列表的位置,直接通过索引赋值:
步骤1:定义组件内的列表变量
// 初始化各个列表 listNG: any[] = []; listCodAML: any[] = []; listTipoRating: any[] = []; listProvince: any[] = []; listGRA: any[] = []; listFiliali: any[] = [];
步骤2:订阅时通过索引分配响应
from(req).pipe( concatMap((request, index) => request.pipe( map(resp => ({ data: resp, index })) )) ).subscribe(({ data, index }) => { switch(index) { case 0: this.listNG = data; break; case 1: this.listCodAML = data; break; case 2: this.listTipoRating = data; break; case 3: this.listProvince = data; break; case 4: this.listGRA = data; break; case 5: this.listFiliali = data; break; } });
步骤3:HTML渲染同方法一
直接绑定对应的列表变量即可。
注意事项
concatMap会保证请求按数组顺序串行执行,每个请求完成后才发起下一个,因此响应的顺序和请求数组完全一致,索引匹配是可靠的。- 如果不需要严格的请求顺序,可以改用
forkJoin并行发起请求,它会等待所有请求完成后一次性返回所有响应,同样可以通过数组索引分配到对应列表。
内容的提问来源于stack exchange,提问作者travis_911
相关产品推荐
相关产品推荐

