Cod*_*n25 5 subscription observable rxjs angular angular-httpclient
当我使用 Angular HttpClient 发出 GET 请求时,我会得到一个可观察的数据并在 RxJS 运算符 mergeMap 中处理它。
现在,一次又一次地抛出 404,我想抓住它。最后,浏览器控制台中不应出现任何错误消息,并且应使用流的下一个值来处理管道。
有这种可能吗?我没有用catchError()来管理它。
这是我的代码的简化版本:
...
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) => {
...
Run Code Online (Sandbox Code Playgroud)
更新:添加了 catchError() 方法
我尝试了这种方式,但是没有检测到错误,并且下一个 mergeMap 不起作用(IDE 不再识别thing.id、thing.type、thing.img_ref等参数):
...
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) => {
...
Run Code Online (Sandbox Code Playgroud)
您需要使用retryor retryWhen(名称非常不言自明) \xe2\x80\x94 这些运算符将重试失败的订阅(一旦发出错误,重新订阅源可观察值。
为了提高id在每次重试 \xe2\x80\x94 时引发 ,您可以将其锁定在一个范围内,如下所示:
const { throwError, of, timer } = rxjs;\r\nconst { tap, retry, switchMap } = rxjs.operators;\r\n\r\nconsole.log(\'starting...\');\r\n\r\ngetDetails(0)\r\n .subscribe(console.log);\r\n\r\n\r\nfunction getDetails(id){\r\n // retries will restart here\r\n return of(\'\').pipe(\r\n switchMap(() => mockHttpGet(id).pipe(\r\n // upon error occurence -- raise the id\r\n tap({ error(err){\r\n id++;\r\n console.log(err);\r\n }})\r\n )), \r\n retry(5) // just limiting the number of retries\r\n // you could go limitless with `retry()`\r\n )\r\n}\r\n\r\nfunction mockHttpGet(id){\r\n return timer(500).pipe(\r\n switchMap(()=>\r\n id >= 3\r\n ? of(\'success: \' + id)\r\n : throwError(\'failed for \' + id)\r\n )\r\n );\r\n}Run Code Online (Sandbox Code Playgroud)\r\n<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>Run Code Online (Sandbox Code Playgroud)\r\n请注意,更明智的做法是设置retry仅在出现错误时重试的条件404。这可以通过以下方式实现retryWhen,例如
// pseudocode\nretryWhen(errors$ => errors$.pipe(filter(err => err.status === \'404\')))\nRun Code Online (Sandbox Code Playgroud)\n\n查看这篇关于 rxjs 中的错误处理的文章,以更加丰富地使用retry和retryWhen。
希望这可以帮助
\n\n更新:还有其他方法可以实现这一点:
\n\nconst { throwError, of, timer, EMPTY } = rxjs;\r\nconst { switchMap, concatMap, map, catchError, take } = rxjs.operators;\r\n\r\nconsole.log(\'starting...\');\r\n\r\ngetDetails(0)\r\n .subscribe(console.log);\r\n\r\n\r\nfunction getDetails(id){\r\n // make an infinite stream of retries\r\n return timer(0, 0).pipe(\r\n map(x => x + id),\r\n concatMap(newId => mockHttpGet(newId).pipe(\r\n // upon error occurence -- suppress it\r\n catchError(err => {\r\n console.log(err);\r\n // TODO: ensure its 404\r\n\r\n // we return EMPTY, to continue\r\n // with the next timer tick\r\n return EMPTY;\r\n })\r\n )),\r\n // we\'ll be fine with first passed success\r\n take(1)\r\n )\r\n}\r\n\r\nfunction mockHttpGet(id){\r\n return timer(500).pipe(\r\n switchMap(()=>\r\n id >= 3\r\n ? of(\'success: \' + id)\r\n : throwError(\'failed for \' + id)\r\n )\r\n );\r\n}Run Code Online (Sandbox Code Playgroud)\r\n<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>Run Code Online (Sandbox Code Playgroud)\r\n| 归档时间: |
|
| 查看次数: |
13777 次 |
| 最近记录: |