Angular HttpClient请求未执行 deleteReward方法接口调用异常
Angular deleteReward 方法未发起HTTP请求问题排查
问题现象
- 执行
deleteReward方法时,仅打印第一行日志console.log('here in delete'),后续逻辑完全不执行 - 浏览器网络面板看不到对应删除接口的请求记录
- 写法几乎完全一致的更新功能可正常运行,仅删除功能出现异常
问题相关代码
deleteReward(id: number): Observable<boolean> { const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem('accessToken'), }) }; console.log('here in delete'); return this.rewards$.pipe( take(1), switchMap(rewards => this._httpClient.post(this._url + 'rewards/delete', { rewardId: id }, httpOptions).pipe( map((res) => { console.log(res); console.log('here in delete 2'); // 查找待删除奖励的索引 const index = rewards.findIndex(item => item.id === id); // 删除对应项 rewards.splice(index, 1); // 推送更新后的奖励列表 this._rewards.next(rewards); return true; }) )) ); }
排查解决步骤
按优先级从高到低排查:
- 检查方法调用处是否添加了订阅
Angular HttpClient返回的是冷Observable,没有调用subscribe()的话,pipe内的所有逻辑(包括switchMap中的HTTP请求)都不会执行。
先对比正常运行的更新方法,确认调用时是否写了订阅逻辑。删除方法如果漏写订阅,就会出现仅打印第一行日志、不发请求的现象。
调用写法参考:// 错误:仅调用方法不订阅,内部逻辑不会触发 // this.rewardService.deleteReward(targetId); // 正确:订阅后才会执行管道逻辑、发起接口请求 this.rewardService.deleteReward(targetId).subscribe({ next: () => { // 删除成功后的业务逻辑 }, error: (err) => { // 错误处理逻辑 } }) - 检查
this.rewards$的初始化状态
如果调用处已经写了订阅,问题根源是rewards$在方法执行时还未发出过任何值。
方法的管道逻辑是先取rewards$的1个值,再进入switchMap发起HTTP请求。如果rewards$基于普通Subject创建,且在调用删除方法时Subject还没有执行过next推送值,take(1)就会持续等待,永远不会进入后续的请求逻辑。
这也能解释为什么更新功能正常:调用更新方法时,rewards$已经拿到列表数据完成过值推送,而删除方法调用时存在时序问题,rewards$还未就绪。
修复方式:将存储奖励列表的_rewards定义为BehaviorSubject并传入初始空数组,保证管道启动时就能拿到值,不会卡住:// 普通Subject无初始值,未推送值时会卡住管道 // private _rewards = new Subject<Reward[]>(); // 改为BehaviorSubject,初始值为空数组 private _rewards = new BehaviorSubject<Reward[]>([]); rewards$ = this._rewards.asObservable(); - 代码逻辑优化
现有逻辑直接用splice修改原数组,会导致Angular变更检测无法识别数据变化,建议改为不可变数据写法,避免视图不更新的问题:// 原直接修改原数组的写法 // const index = rewards.findIndex(item => item.id === id); // rewards.splice(index, 1); // this._rewards.next(rewards); // 优化为返回新数组的写法 const updatedRewards = rewards.filter(item => item.id !== id); this._rewards.next(updatedRewards);
内容的提问来源于stack exchange,提问作者Deniz Celebi
相关产品推荐
相关产品推荐

