如何在API调用时正确显示与隐藏Mat Spinner?
解决API调用时Mat Spinner不生效的问题
你的问题核心确实是subscribe的异步特性导致的——你现在的代码里,this.loading = false;是同步执行的,API请求还在后台处理时,这句代码已经把loading改成false了,Spinner根本来不及显示,甚至因为请求太快出现了短暂的空白屏幕。
给你几个简便的解决方法,按优雅程度排序:
方法1:用RxJS的finalize操作符(推荐)
这个操作符会在Observable完成(不管成功还是失败)的时候执行回调,完美解决异步状态重置的问题,代码也最简洁:
this.loading = true; this.ticketModelService.farmerList .pipe(finalize(() => this.loading = false)) // 请求结束(成功/失败)都会关闭loading .subscribe(value => { if (value) { this.farmerList = value.data; this.paginationNumbers = value.recordsFiltered; } });
方法2:在subscribe的回调里统一处理loading状态
如果不想用RxJS操作符,也可以把loading=false放到订阅的next和error回调里,确保无论请求结果如何都能重置状态:
this.loading = true; this.ticketModelService.farmerList .subscribe({ next: (value) => { if (value) { this.farmerList = value.data; this.paginationNumbers = value.recordsFiltered; } this.loading = false; }, error: (err) => { // 这里可以加错误提示,比如给用户弹个Toast console.error('获取农户列表失败', err); this.loading = false; } });
额外解决:2毫秒空白屏幕的问题
如果API请求太快,Spinner只闪一下或者出现空白,你可以给loading加个最小显示时长(比如500毫秒),避免这种尴尬的情况:
import { timer, forkJoin } from 'rxjs'; this.loading = true; // 强制至少显示500毫秒的loading const minLoading$ = timer(500); const apiRequest$ = this.ticketModelService.farmerList; forkJoin([minLoading$, apiRequest$]).subscribe(([_, value]) => { if (value) { this.farmerList = value.data; this.paginationNumbers = value.recordsFiltered; } this.loading = false; }, (err) => { console.error('请求失败', err); this.loading = false; });
这样哪怕API请求2毫秒就完成,Spinner也会显示够500毫秒,用户体验会好很多。
内容的提问来源于stack exchange,提问作者Prashant Pimpale
相关产品推荐
相关产品推荐

