javascript - 如何使用 Rxjs switchMap 来抛出错误
问题描述
我已经为 fetch 函数创建了一个包装器。根据下面的代码,test_3 通过了,但是 test_1 和 test_2 怎么会命中成功回调而不是错误回调呢?我怀疑我使用 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.com').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.com').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.com').subscribe(
response => console.log('should hit this'),
errorResponse => console.log('should not hit this'),
);
// test_3 console result:
// response.ok = true
// should hit this
请不要建议我使用 rxjs 的 ajax。
解决方案
你可以直接在里面返回一个 Promise switchMap
。
switchMap(response => response.ok
? getBody(response)
: getBody(response).then(body => {
throw { status: response.status, statusText: response.statusText, body }
}))
)
不要async
使用switchMap(async (response: Response) => { })
!
问题是这async
会导致switchMap
返回任何你返回的 Observable。所以在你的switchMap
ifresponse.ok == false
你返回一个which 然后向你的成功回调Observable<Observable<never>>
发出一个。Observable<never>
这里有一些在内部抛出错误的一般方法switchMap
。
1. 返回一个错误的 Observable。
switchMap(response => response.ok
? of(successObject)
: throwError(errorObject)
)
2.直接抛出错误
switchMap(response => {
if (response.ok) {
return of(successObject)
} else {
throw errorObject
}
})
3. 返回一个错误的 Promise
switchMap(response => response.ok
? Promise.resolve(successObject)
: Promise.reject(errorObject)
)