หยุดท่อตรงกลาง

Dec 15 2020

ในแอปเชิงมุมของฉันฉันมีตัวสกัดกั้นการรีเฟรชโทเค็นซึ่งสกัดกั้นข้อผิดพลาด 401 ที่ไม่ได้รับอนุญาตพยายามรีเฟรชโทเค็นการเข้าถึงและดำเนินการตามคำขอ http ดั้งเดิมอีกครั้ง

จุดสิ้นสุดการรีเฟรชโทเค็นอาจล้มเหลวในบางกรณีและส่งคืนข้อผิดพลาดที่ทราบ (ในกรณีของฉันเป็นข้อผิดพลาด 400 invalid_grant)

ส่วนของ interceptor ที่รีเฟรชโทเค็น:

 return this.httpClient
  .request('POST', "token", { observe: 'response' })
  .pipe(
    map(response => {
      // some logic when the token was refreshed successfully
    }),
    catchError(err => {
      this.routingService.navigateToLoginNoQuery();
      return throwError(err); // a 400 - invalid_grant error
    })
  );

เมื่อสิ่งนี้เกิดขึ้นมันจะไปยังตัวดำเนินการ catchError ซึ่งทำ 2 สิ่ง: ออกจากระบบ (ด้วยการเปลี่ยนเส้นทางไปยังหน้าล็อกอิน) และส่งคืน throwError (ข้อผิดพลาด) ข้อผิดพลาดนี้เกิดขึ้นคือข้อผิดพลาด 400-Invalid_grant

ซึ่งทำให้ข้อผิดพลาดใหม่มาถึงตัวดำเนินการ catchError บางตัวในฟังก์ชันที่ทริกเกอร์โทเค็นการรีเฟรช

สำหรับบริบท: ฉันบันทึกข้อผิดพลาดในบล็อก catch และฉันต้องการหลีกเลี่ยงการบันทึกข้อผิดพลาดประเภทนี้เพราะโดยปกติแล้วจะหมายความว่าโทเค็นของผู้ใช้หมดอายุเท่านั้น

สิ่งที่ฉันต้องการจะทำคือหยุดห่วงโซ่ตัวดำเนินการนี้และเปลี่ยนเส้นทางไปยังหน้าเข้าสู่ระบบ

เป็นไปได้หรือไม่ที่จะหยุดท่อตรงกลางและหลีกเลี่ยงการไปที่ catchError ด้านนอกและไปยังตัวดำเนินการถัดไปในท่อ?

คำตอบ

1 GuerricP Dec 14 2020 at 23:25

คุณสามารถคืนค่าว่างObservableเพื่อป้องกันไม่ให้เหตุการณ์หรือข้อผิดพลาดไปถึงส่วนประกอบที่กำลังจะถูกทำลาย:

return this.httpClient
  .request('POST', "token", { observe: 'response' })
  .pipe(
    map(response => {
      // some logic when the token was refreshed successfully
    }),
    catchError(err => {
      this.routingService.navigateToLoginNoQuery();
      return EMPTY;
    })
  );
MishaBorisov Dec 14 2020 at 23:30

หากฉันเข้าใจการแก้ไขคำถามแล้วผู้ประกอบการtakeUntilอาจช่วยคุณได้ ตัวอย่างจะมีลักษณะดังนี้:

export class MyHttpInterceptor implements HttpInterceptor {
  anyError = new Subject();

  intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req)
      .pipe(
         takeUntil(this.anyError),
         catchError(err => {
             this.anyError.next();
             ...
         }
      )
  }
}