TypeScript - איך אני תופס שגיאה בשני נקודות שונות ב-RxJS/Angular?


נניח את הקטע הקוד הזה ב-Angular 2:

export class ApiService {
  // do stuff
  request(...): Observable<Response> {
    return this.http.request(...)
      .share()
      .catch((error: any) => {
        let errMsg = 'my error';
        // do more stuff...
        // tried: throw errMsg;
        // tried: return Observable.throw(errMsg);
      });
  }
}

אז :

api.request(...).catch(() => {
  console.log('caught');
  return Observable.from([]);
}).subscribe({
  console.log('everything fine');
});

ה-next callback שעובר ל-subscribe אכן נקרא כשמבצעים את הבקשה בהצלחה, אבל ה-callback שעובר ל-catch לא נקרא.

ניסיתי להתמודד עם השגיאה בשני חלקים שונים בקוד שיש להם אחריות שונה. הייתי רוצה שהודעת השגיאה שתיזרק ב-ApiService.request תסתיים בקולבק השני כדי שאוכל לחדד עוד יותר את התגובה שלי למשתמש. ניסיתי גם throw errMsg וגם להחזיר Observable.throw(errMsg).

הסיבה לכך שאני משתמש ב-.share() עבור האובזרבל היא כי אני לא רוצה שלקוח ה-HTTP ייצר בקשה אחת עבור כל מנוי.

באיזה מקום אני טועה בזה?

עריכה:

הדוגמה שלי למעלה לא באמת תיארה את הבעיה שהייתה לי. קטע הקוד השני הזה מאפשר לשחזר אותה:

const a = Rx.Observable.create(function(observer){
  observer.error('h');
}).share().catch(err=> {
  console.error('first place',err);
  throw 'err'
})
.subscribe(() => null)
.subscribe(console.log, console.error);

המנוי הראשון נכשל בלתפוס את השגיאה (בגלל שלא היה מוגדר מטפל בשגיאות) ושבר את השרשרת למנוי השני.

תשובה #1

ממה שהבנתי אתה רוצה לתפוס את השגיאה בשני מקומות. לפי התיעוד אתה צריך להשתמש ב-throw. ניסיתי וזה עובד לי בסדר. הנה קטע הקוד:

const a = Rx.Observable.create(function(observer){
    observer.error('h');
});

a.catch(err=> {
   console.error('first place',err);
   throw 'err'
}).subscribe(console.log,console.error);

פלט

x first place 
x err 

JSBin : https://jsbin.com/jefalazibo/edit?html,js,console

בקוד של הרכיב אין צורך לכתוב עוד catch. subscribe לוקח שלוש פונקציות כארגומנטים

 subscribe(onSuccess, onError, onComplete);

תיעוד: https://github.com/ReactiveX/rxjs/blob/master/src/operator/catch.ts (בדוק דוגמה 3)