Angular调用API首次加载报rxjs subscribeTo错误 刷新后正常如何解决
问题根因
- RxJS catch 操作符返回值不符合规范
你代码中使用的rxjscatch(rxjs 6+对应catchError)要求必须返回一个Observable流,但是你当前catch分支直接返回了普通Error对象,不属于可订阅的流类型,因此rxjs处理错误时抛出了subscribeTo类型错误。 - 首次加载时请求依赖属性未初始化
首次进入页面时,this.userId、authService.getToken()两个请求依赖的属性还没有完成初始化赋值(比如用户信息是异步从本地存储/后端接口获取,组件首次渲染时还没返回结果),导致第一次请求参数异常、鉴权失败触发catch分支,进而抛出类型错误。刷新页面时这些值已经缓存完成,所以请求正常。 - 代码逻辑冗余
getOwnedEvents方法定义了user_id入参,但实际请求时用的是this.userId,入参完全没有使用,也可能出现参数传递不匹配的问题。
另外你日志中输出的500错误是后端get_profile_image接口的内部错误,和本次的rxjs报错无关,单独排查后端接口逻辑即可。
修复步骤
1. 修正catch分支的返回值
保证catch分支返回可订阅的流,根据你使用的rxjs版本对应修改:
rxjs 5版本:
// 顶部先引入依赖 import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/throw'; // 修改getOwnedEvents的catch部分 .catch( (error) => { let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; console.log(errMsg); } else { errMsg = error.message ? error.message : error.toString(); console.log(errMsg); } // 替换原有直接返回error的逻辑,返回Observable错误流 return Observable.throw(errMsg); } )
rxjs 6+版本:
// 顶部先引入依赖 import { throwError } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; // 修改getOwnedEvents的流处理逻辑为pipe写法 return this.http.get(url, {headers}) .pipe( map((data) => { console.log(data); return data['payload']['events']; }), catchError((error) => { let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; console.log(errMsg); } else { errMsg = error.message ? error.message : error.toString(); console.log(errMsg); } return throwError(() => new Error(errMsg)); }) )
2. 调整请求触发逻辑,保证依赖值初始化完成
不要直接在ngAfterViewInit触发请求,增加依赖值判断,未初始化完成时延迟重试:
onLoadTable() { const token = this.authService.getToken(); // 同时判断token和userId都存在再发起请求 if(token == null || !this.userId){ setTimeout(() => this.onLoadTable(), 300); return; } // 原有业务逻辑不变 this.processing = true; this.errorMsg = ""; console.log("in onLoadTable."); this.getOwnedEvents(this.userId) .subscribe( data => { console.log(data); this.processing = false; this.dataSource.data = data; this.paginator.firstPage(); }, (err) => { this.processing = false; var errorReturned = (err.error != undefined && err.error['message'] != undefined) ? err.error['message'] : ""; this.errorMsg = "Error while retrieving event list: " + errorReturned; } ); }
3. 清理冗余参数
修正getOwnedEvents的参数逻辑,避免混淆:
// 方案1:删除无用的user_id参数 getOwnedEvents(retries:number=0) { let url = this.apiURL + 'users/' + this.userId + '/get_all_owned_events'; // 剩余逻辑不变 } // 方案2:使用传入的user_id参数 getOwnedEvents(user_id, retries:number=0) { let url = this.apiURL + 'users/' + user_id + '/get_all_owned_events'; // 剩余逻辑不变 }
内容的提问来源于stack exchange,提问作者Nolan Mayersky
相关产品推荐
相关产品推荐

