TypeScript - RxJS 5 עם Angular 2: לנסות שוב Observable שנכשל ואז להעביר את השגיאה


כאשר בקשת HTTP נכשלה, אני רוצה לנסות שוב פעמיים במרווח של שנייה אחת. אם היא נכשלת שוב בפעם השלישית, אני רוצה להעביר את השגיאה הזו למתבוננים. אני נתקל בקושי עם החלק האחרון הזה.

בקשת HTTP מ-DataService.get()

return this.http.get(url,options)
    .retryWhen(errors => errors.delay(1000).take(2))
    .catch((res)=>this.handleError(res));

מנוי

this.dataSvc.get('/path').subscribe(
    res => console.log(res),
    err => console.error(err),
    () => console.log('Complete')
);

השרת שלי מוגדר תמיד להחזיר שגיאה (סטטוס 400 בקשה שגויה).

  • אני רוצה שהאפליקציה תבצע בקשה שנייה, תבצע בקשה שלישית, ואז תזרוק את השגיאה שתילקח על ידי this.handleError()

  • מה שקורה בפועל: היישום מבצע בקשה שנייה, מבצע בקשה שלישית, ואז ה-Observable מסתיים ללא שגיאה (הדפסה של "Complete" למסוף)

Angular 2 rc.6, RxJS 5 beta 11, Typescript 2.0.2

תשובה #1

השתמשתי באופרטור scan:

return this.http.get(url,options)
    .retryWhen(errors => errors.delay(1000).scan((acc,source,index)=>{
        if(index) throw source;
    }))
    .catch((res)=>this.handleError(res));

הפרמטרים של scan():

  • acc: מצבר (תחשוב על Array.reduce()). אם תשנה אותו ותחזיר אותו, הערך החדש יסופק כפרמטר acc בהרצה הבאה
  • source: הערך (או החריגה) שהופק על ידי הפעולה הקודמת (delay(), שמעבירה אותו בעצמה מ-errors)
  • index: אינדקס של הערך הנפלט הנוכחי (מתחיל מאפס)

זה מבצע 3 בקשות HTTP (אינני יודע למה; הייתי מצפה ל-2). בכישלון השלישי, הוא זורק את source -- השגיאה שהופקה -- כדי שתיתפס על ידי handleError()