Error handling inside RxJS mergeMap operator
当我使用Angular HttpClient发出GET请求时,我得到一个可观察到的结果,并在RxJS运算符mergeMap中对其进行处理。
现在,发生了一次又一次抛出404的错误,我想抓住它。 最后,浏览器控制台中不应出现任何错误消息,并且应使用流的下一个值来处理管道。
有可能吗? 我没有用catchError()管理它。
这是我的代码的简化版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ... this.service1.getSomeStuff().pipe( mergeMap((someStuff) => { return from(stuff); }), mergeMap((stuff) => { return this.service2.getMoreStuff(stuff.id); // Here I need some error handling, if 404 occurs }), mergeMap((things) => { return from(things).pipe( mergeMap((thing) => { if (allLocations.some(x => x.id === metaData.id)) { return this.service2.getMore(thing.id, thing.type, thing.img_ref); } }), map((thing) => { ... |
更新:使用catchError()添加方法
我以这种方式进行了尝试,但是未检测到错误,并且下一个mergeMap不起作用(IDE不再识别诸如Thing.id,Thing.Type,Thing.img_ref之类的参数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ... this.service1.getSomeStuff().pipe( mergeMap((someStuff) => { return from(stuff); }), mergeMap((stuff) => { return this.service2.getMoreStuff(stuff.id).pipe( catchError(val => of(`Error`)) ); }), mergeMap((things) => { return from(things).pipe( mergeMap((thing) => { if (allLocations.some(x => x.id === metaData.id)) { return this.service2.getMore(thing.id, thing.type, thing.img_ref); } }), map((thing) => { ... |
您将需要使用
要在每次重试时提高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | const { throwError, of, timer } = rxjs; const { tap, retry, switchMap } = rxjs.operators; console.log('starting...'); getDetails(0) .subscribe(console.log); function getDetails(id){ // retries will restart here return of('').pipe( switchMap(() => mockHttpGet(id).pipe( // upon error occurence -- raise the id tap({ error(err){ id++; console.log(err); }}) )), retry(5) // just limiting the number of retries // you could go limitless with `retry()` ) } function mockHttpGet(id){ return timer(500).pipe( switchMap(()=> id >= 3 ? of('success: ' + id) : throwError('failed for ' + id) ) ); } |
1 | <script src="https://unpkg.com/[email protected]/bundles/rxjs.umd.min.js"> |
请注意,最好有条件的
1 2 | // pseudocode retryWhen(errors$ => errors$.pipe(filter(err => err.status === '404'))) |
请查看有关rxjs中的错误处理的本文,以使
希望这可以帮助
更新:还有其他方法可以实现这一点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | const { throwError, of, timer, EMPTY } = rxjs; const { switchMap, concatMap, map, catchError, take } = rxjs.operators; console.log('starting...'); getDetails(0) .subscribe(console.log); function getDetails(id){ // make an infinite stream of retries return timer(0, 0).pipe( map(x => x + id), concatMap(newId => mockHttpGet(newId).pipe( // upon error occurence -- suppress it catchError(err => { console.log(err); // TODO: ensure its 404 // we return EMPTY, to continue // with the next timer tick return EMPTY; }) )), // we'll be fine with first passed success take(1) ) } function mockHttpGet(id){ return timer(500).pipe( switchMap(()=> id >= 3 ? of('success: ' + id) : throwError('failed for ' + id) ) ); } |
1 | <script src="https://unpkg.com/[email protected]/bundles/rxjs.umd.min.js"> |