Angular 4中loading.dismiss()在handleError()方法中失效求助
嘿,我懂你遇到的问题啦——你想让加载提示框不管请求成功还是失败都能正常关闭,但不知道怎么在错误处理的场景里调用loading.dismiss()对吧?其实不用纠结在handleError里单独处理,我们可以用RxJS的操作符来统一搞定这个逻辑!
解决方案:用RxJS操作符统一处理加载框关闭
最优雅的方式是利用RxJS的finally(RxJS 5及以下)或finalize(RxJS 6+)操作符,它们会在Observable的生命周期结束时(不管是正常完成还是抛出错误)执行指定逻辑,这样就能确保加载框一定会被关闭,不用在成功回调和错误处理里重复写代码。
修改后的完整代码示例(RxJS 5及以下)
import { Injectable } from '@angular/core'; import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/finally'; import { LoadingController } from 'ionic-angular'; @Injectable() export class SharedProvider { private _postsURL = "https://jsonplaceholder.typicode.com/posts"; constructor(private http: Http, public loadingCtrl: LoadingController) { } getPosts(): Observable<IPosts[]> { let loading = this.loadingCtrl.create({ content: 'loading...' }); loading.present(); return this.http.get(this._postsURL) .map((response: Response) => { return <IPosts[]>response.json(); }) .catch(this.handleError) // 核心:不管请求成功/失败,都会执行这里的关闭逻辑 .finally(() => { loading.dismiss(); }); } private handleError(error: Response | any) { let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = body.error || JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return Observable.throw(errMsg); } }
如果用的是RxJS 6+版本
RxJS 6+对操作符的导入和使用方式做了调整,需要用pipe来组合操作符,且操作符名称改为finalize:
import { Injectable } from '@angular/core'; import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs'; import { map, catchError, finalize } from 'rxjs/operators'; import { LoadingController } from 'ionic-angular'; @Injectable() export class SharedProvider { private _postsURL = "https://jsonplaceholder.typicode.com/posts"; constructor(private http: Http, public loadingCtrl: LoadingController) { } getPosts(): Observable<IPosts[]> { let loading = this.loadingCtrl.create({ content: 'loading...' }); loading.present(); return this.http.get(this._postsURL).pipe( map((response: Response) => <IPosts[]>response.json()), catchError(this.handleError), finalize(() => loading.dismiss()) ); } private handleError(error: Response | any) { let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = body.error || JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return throwError(() => errMsg); } }
为什么这个方法有效?
finally/finalize操作符会监听Observable的整个生命周期,不管请求是成功完成还是抛出错误,都会触发回调函数,所以加载框100%会被关闭。- 这种写法避免了重复代码,也不用把
loading变量传递到handleError方法里,逻辑更清晰简洁。
内容的提问来源于stack exchange,提问作者Jayesh
相关产品推荐
相关产品推荐

