<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                上節的情況下,分別在班級管理、個人中心、注銷時發生了401錯誤。雖然我們可以在三個組件中分別加入判斷是否發生401錯誤的代碼,但這么做明顯是在造重復的輪子。 ```typescript this.httpClient.get(url) .subscribe(() => console.log('success'), error => 判斷是否發生了401,發生401則注銷應用,顯示登錄窗口); ``` ## 再談攔截器 繼續開始之前,我們需要再復習下攔截器: ![image-20210309104836454](https://img.kancloud.cn/1b/86/1b86f3c365fbc64f972e3a6c7e8734d4_1474x456.png) 通過上圖不難發現,攔截器不但可以對請求進行攔截,還可以對后臺的響應進行攔截。 在前面的章節中,我們其實已經偷偷的說明了后期要加入一個登錄的攔截器了: ![image-20210309110421080](https://img.kancloud.cn/11/b7/11b78fa5cc2228b8257f6e983ac6d590_1714x868.png) ## 攔截異常 在`XAuthTokenInterceptor`中我們已經初步的掌握了使用`tap()`操作符對響應進行監聽的方法: ```typescript return next.handle(request).pipe(tap(input => { // 僅當input類型為HttpResponseBase,才嘗試獲取token并更新 if (input instanceof HttpResponseBase) { const httpHeader = input.headers; const xAuthToken = httpHeader.get('x-auth-token'); if (xAuthToken !== null) { this.setToken(xAuthToken); } } })); ``` 本例中,我們將使用一個新的操作符`catchError()`來監聽后臺響應數據是否為**認證失敗**。 ### 初始化 來到`src/app`文件夾,初始化`UnAuth`攔截器: ```bash panjie@panjies-iMac app % pwd /Users/panjie/github/mengyunzhi/angular11-guild/first-app/src/app panjie@panjies-iMac app % ng g interceptor unAuth CREATE src/app/un-auth.interceptor.spec.ts (417 bytes) CREATE src/app/un-auth.interceptor.ts (411 bytes) ``` ### 應用攔截器 有了攔截器后,我們將其添加到App模塊中以使其生效: ```typescript +++ b/first-app/src/app/app.module.ts @@ -16,6 +16,7 @@ import {XAuthTokenInterceptor} from './x-auth-token.interceptor'; import {WelcomeComponent} from './welcome.component'; import { NavComponent } from './nav/nav.component'; import {ApiInterceptor} from './api.interceptor'; +import {UnAuthInterceptor} from './un-auth.interceptor'; @NgModule({ @@ -39,7 +40,8 @@ import {ApiInterceptor} from './api.interceptor'; ], providers: [ {provide: HTTP_INTERCEPTORS, useClass: XAuthTokenInterceptor, multi: true}, - {provide: HTTP_INTERCEPTORS, useClass: ApiInterceptor, multi: true} + {provide: HTTP_INTERCEPTORS, useClass: ApiInterceptor, multi: true}, + {provide: HTTP_INTERCEPTORS, useClass: UnAuthInterceptor, multi: true} ], bootstrap: [IndexComponent] }) ``` ### catchError 我們在編寫程序時會遇到異常,通常一些可見的異常使用`try catch`來解決。RxJS借鑒了這一思想。當數據流沒有按預期返回時,將向上拋出異常。打個現實生活中可能沒有的比方,我們關注了某個喜歡的人,此后我們將會收到該人發布的新狀態,但有一天這個不走尋常路是被人**發現**了,自此該賬號被永久封禁。在此事件中,這個永久封禁便是個異常事件。在該賬號被封的時候我們將得到一個某賬號被封的通知,這便是RxJS中的異常。 在Angular的Http請求中,將兩種情況視為異常: 1. 服務端的非2XX錯誤,比如資源未找到時發生的404錯語,用戶認證失敗時發生的401錯語,權限校驗時發生的403錯誤等。 2. 客戶端發生了網絡錯誤,比如當前計算機處理脫機狀態,無法訪問外部網絡;或是當前計算機的網卡因為驅動的問題而未正常工作等。 我們在此僅考慮第1種情況,服務端的非2xx錯誤。 與正常數據可以使用`tap()`監聽一樣,異常的數據可以`catchError()`操作符來監聽。與`tap()`操作符并不要求有返回值不同,`catchError()`操作符要求必須有返回值,該返回值可以通過`RxJS`提供的`throwError()`方法來快速實現: ```typescript +++ b/first-app/src/app/un-auth.interceptor.ts @@ -5,7 +5,8 @@ import { HttpEvent, HttpInterceptor } from '@angular/common/http'; -import {Observable} from 'rxjs'; +import {Observable, throwError} from 'rxjs'; +import {catchError} from 'rxjs/operators'; @Injectable() export class UnAuthInterceptor implements HttpInterceptor { @@ -14,6 +15,11 @@ export class UnAuthInterceptor implements HttpInterceptor { } intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { - return next.handle(request); + return next.handle(request) + .pipe(catchError(error => { ① + console.log('發生了錯誤', error); + // 使用throwError()繼續向上拋出異常 + return throwError(error); ② + })); } } ``` - ① `catchError`操作符同樣接收回調函數做為參數 - ② 使用`throwError()`方法向上繼續拋出異常 此時當點擊注銷時(需要按上節的步驟,模擬半個小時沒有登錄),將在控制臺中發現如下日志: ![image-20210409163335140](https://img.kancloud.cn/fb/a3/fba38f093116527cb6b157c137a5e9a6_3192x140.png) 這其中的`status: 401`就是我們想要進行判斷的返回狀態碼。 ```typescript +++ b/first-app/src/app/un-auth.interceptor.ts @@ -17,7 +17,9 @@ export class UnAuthInterceptor implements HttpInterceptor { intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { return next.handle(request) .pipe(catchError(error => { - console.log('發生了錯誤', error); + if (error.status === 401) { + console.log('發生了401錯誤, 通知應用顯示登錄界面', error); + } // 使用throwError()繼續向上拋出異常 return throwError(error); })); ``` 此時一旦發生401錯誤,則會在控制臺中打印一條相關日志。401被判斷出來后,通知應用這個狀態則可以實現:當用戶因長時間未操作而發生被動注銷時,及時地顯示登錄界面了。 下一小節中,我們將建立一個服務,并將其分別注入到攔截器及`Index`組件,并以該服務為紐帶,在請求發生401時將通知發送給`Index`組件。 | 名稱 | 鏈接 | | ------------ | ------------------------------------------------------------ | | 處理請求錯誤 | [https://angular.cn/guide/http#handling-request-errors](https://angular.cn/guide/http#handling-request-errors) | | 本節源碼 | [https://github.com/mengyunzhi/angular11-guild/archive/step6.7.1.zip](https://github.com/mengyunzhi/angular11-guild/archive/step6.7.1.zip) |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看