我已经为获取函数创建了一个包装器。根据下面的代码,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。
答案 0 :(得分:4)
获取不会为您抛出错误
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
从fetch()返回的Promise不会因HTTP错误状态而拒绝 即使响应是HTTP 404或500,它也会解析 通常(将ok状态设置为false),并且只会在 网络故障或是否有任何阻止请求完成的事情。
更新: 看来您的api调用正在返回401,并且在获取承诺中将被拒绝,但是您仍然不能依靠获取来正确拒绝。请参阅以下主题
https://github.com/github/fetch/issues/201
对于您的代码,switchMap无法处理的原因是您返回的不是throw Promise的throwError(您将函数标记为async)
将throwError(...)
更改为throwError().toPromise()
可以正常工作。但同样不要依赖提取来正确拒绝
答案 1 :(得分:1)
删除async
中的switchMap
,然后使用of
返回一个Observable。
const http = (url) =>
from(fetch(new Request(url))
.pipe(
retry(3),
catchError(error => { // fetch will throw error if page not found.
return of(new Response(null, { status: 404, statusText: 'Page not found' }));
}),
switchMap((response: Response) =>
response.ok
? of(response) // return an observable here using 'of'
: throwError(response)
),
);
async
导致switchMap
返回您所返回内容的Observable。因此,在您的switchMap
中,如果response.ok == false
返回了一个Observable<Observable<never>>
,则它向成功回调发出了一个Observable<never>
。