admin管理员组文章数量:1399116
I have create a wrapper for fetch function. Based on the code below, test_3 passed but how e test_1 and test_2 hit success callback instead of error callback? I suspect there is something wrong in the way I use throwError.
import { from, throwError } from 'rxjs'; // version 6.5.2
import { retry, catchError, switchMap } from 'rxjs/operators';
function getBody(response: Response): Promise<any> {
const headers = response.headers;
if (headers.has('content-type')) {
const contentType: string = headers.get('content-type');
if (contentType.includes('json')) return response.json();
}
return response.text();
}
const http = (url) =>
from(fetch(new Request(url))
.pipe(
retry(3),
catchError(error => { // fetch will throw error if page not found.
console.log('hit catchError')
return of(new Response(null, { status: 404, statusText: 'Page not found' }));
}),
switchMap(async (response: Response) => {
console.log('response.ok = ', response.ok);
return response.ok
? getBody(response) // all status >= 200 and < 400
: throwError({
status: response.status,
statusText: response.statusText,
body: await getBody(response)
});
}),
);
// test_1
http('').subscribe(
response => console.log('should not hit this'),
errorResponse => console.log('should errorResponse.status = 404'),
);
// test_1 console result:
// hit catchError
// response.ok = false
// should not hit this
// test_2
http('').subscribe(
response => console.log('should not hit this'),
errorResponse => console.log('should errorResponse.status = 401'),
);
// test_2 console result:
// response.ok = false
// should not hit this
// test_3
http('').subscribe(
response => console.log('should hit this'),
errorResponse => console.log('should not hit this'),
);
// test_3 console result:
// response.ok = true
// should hit this
Please do not propose me to use rxjs's ajax.
I have create a wrapper for fetch function. Based on the code below, test_3 passed but how e test_1 and test_2 hit success callback instead of error callback? I suspect there is something wrong in the way I use throwError.
import { from, throwError } from 'rxjs'; // version 6.5.2
import { retry, catchError, switchMap } from 'rxjs/operators';
function getBody(response: Response): Promise<any> {
const headers = response.headers;
if (headers.has('content-type')) {
const contentType: string = headers.get('content-type');
if (contentType.includes('json')) return response.json();
}
return response.text();
}
const http = (url) =>
from(fetch(new Request(url))
.pipe(
retry(3),
catchError(error => { // fetch will throw error if page not found.
console.log('hit catchError')
return of(new Response(null, { status: 404, statusText: 'Page not found' }));
}),
switchMap(async (response: Response) => {
console.log('response.ok = ', response.ok);
return response.ok
? getBody(response) // all status >= 200 and < 400
: throwError({
status: response.status,
statusText: response.statusText,
body: await getBody(response)
});
}),
);
// test_1
http('http://this_url_not_exists.').subscribe(
response => console.log('should not hit this'),
errorResponse => console.log('should errorResponse.status = 404'),
);
// test_1 console result:
// hit catchError
// response.ok = false
// should not hit this
// test_2
http('http://this_url_require_authentication.').subscribe(
response => console.log('should not hit this'),
errorResponse => console.log('should errorResponse.status = 401'),
);
// test_2 console result:
// response.ok = false
// should not hit this
// test_3
http('http://myurl.').subscribe(
response => console.log('should hit this'),
errorResponse => console.log('should not hit this'),
);
// test_3 console result:
// response.ok = true
// should hit this
Please do not propose me to use rxjs's ajax.
Share Improve this question edited May 16, 2019 at 3:40 Simon asked May 15, 2019 at 1:38 SimonSimon 1,5363 gold badges17 silver badges25 bronze badges2 Answers
Reset to default 3fetch won't throw error for you
https://developer.mozilla/en-US/docs/Web/API/Fetch_API/Using_Fetch
The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from pleting.
Update: Looks like your api call is returning 401 and will be rejected in fetch promise, but you still can't rely on fetch to reject properly. please see the below thread
https://github./github/fetch/issues/201
and regarding your code the reason it is not handle by switchMap is you return throwError which is not a promise ( you mark function with async)
change throwError(...)
to throwError().toPromise()
will work properly. but again don't rely on fetch to reject properly
You can return a Promise inside switchMap
directly.
switchMap(response => response.ok
? getBody(response)
: getBody(response).then(body => {
throw { status: response.status, statusText: response.statusText, body }
}))
)
Don't use async
as in switchMap(async (response: Response) => { })
!
The problem is that async
causes switchMap
to return an Observable of whatever you return. So in your switchMap
if response.ok == false
you returned an Observable<Observable<never>>
which then emitted an Observable<never>
to your success callback.
Here are a few general ways to throw an error inside switchMap
.
1. Return an Observable that errors.
switchMap(response => response.ok
? of(successObject)
: throwError(errorObject)
)
2. Throw an error directly
switchMap(response => {
if (response.ok) {
return of(successObject)
} else {
throw errorObject
}
})
3. Return a Promise that errors
switchMap(response => response.ok
? Promise.resolve(successObject)
: Promise.reject(errorObject)
)
本文标签: javascriptHow to use Rxjs switchMap to throwErrorStack Overflow
版权声明:本文标题:javascript - How to use Rxjs switchMap to throwError - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744212704a2595495.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论