Angular HttpClient 可观察未完成
Angular HttpClient observable not completing
我有以下代码:
// in a service
downloadCSV(): Observable<Blob> {
return this.httpClient.get(`${apiUrl}/a.csv`, {responseType: 'blob'});
}
// in component
onDownloadClicked(event: MouseEvent) {
this.downloading = true;
this.service.downloadCSV()
.pipe(finalize(() => this.downloading = false))
.subscribe(
(data: Blob) => {
console.log(data);
},
(error) => {
console.error(error);
alert('Sorry, something wet wrong. Try again.');
},
() => {
console.log('completed!');
}
);
}
数据已正确记录,但 'completed!' 未记录且从未调用 finalize。
编辑:
所以在进一步调查中,问题似乎与添加身份验证的拦截器有关 header。
如果拦截器被绕过(并在服务器上禁用身份验证),则可观察对象将无错误地完成。
我不明白为什么会这样。可能与克隆请求有关?
//interceptor code
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let scope: string;
// only inject tokens for the following scopes
if (req.url.indexOf('https://graph.microsoft.com') === 0) {
scope = 'https://graph.microsoft.com';
}
else if (req.url.indexOf('https://management.azure.com') === 0) {
scope = 'https://management.azure.com';
}
else if (req.url.indexOf(environment.apiUrl) === 0) {
scope = environment.appId;
}
if (scope) {
return this.authService.getToken(scope).pipe(
switchMap((token) => {
let newReq;
if (token) {
const JWT = `Bearer ${token}`;
newReq = req.clone({
setHeaders: {
Authorization: JWT,
}
});
}
return next.handle(newReq || req);
})
);
}
else {
return next.handle(req);
}
}
原来问题出在我的授权服务的getToken函数中。我忘记在返回令牌后完成可观察的!由于 httpClient.get observable 是通过我的 getToken observable 切换映射的,这导致我在 onDownloadClicked 中的订阅永远无法完成。
// from my auth service
getToken(resource: string): Observable<string> {
return Observable.create((observer: Observer<string>) => {
this.context.acquireToken(resource, (error, token) => {
if (token) {
observer.next(token);
observer.complete(); // this was missing
}
else {
this.login();
}
});
});
}
我有以下代码:
// in a service
downloadCSV(): Observable<Blob> {
return this.httpClient.get(`${apiUrl}/a.csv`, {responseType: 'blob'});
}
// in component
onDownloadClicked(event: MouseEvent) {
this.downloading = true;
this.service.downloadCSV()
.pipe(finalize(() => this.downloading = false))
.subscribe(
(data: Blob) => {
console.log(data);
},
(error) => {
console.error(error);
alert('Sorry, something wet wrong. Try again.');
},
() => {
console.log('completed!');
}
);
}
数据已正确记录,但 'completed!' 未记录且从未调用 finalize。
编辑:
所以在进一步调查中,问题似乎与添加身份验证的拦截器有关 header。
如果拦截器被绕过(并在服务器上禁用身份验证),则可观察对象将无错误地完成。
我不明白为什么会这样。可能与克隆请求有关?
//interceptor code
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let scope: string;
// only inject tokens for the following scopes
if (req.url.indexOf('https://graph.microsoft.com') === 0) {
scope = 'https://graph.microsoft.com';
}
else if (req.url.indexOf('https://management.azure.com') === 0) {
scope = 'https://management.azure.com';
}
else if (req.url.indexOf(environment.apiUrl) === 0) {
scope = environment.appId;
}
if (scope) {
return this.authService.getToken(scope).pipe(
switchMap((token) => {
let newReq;
if (token) {
const JWT = `Bearer ${token}`;
newReq = req.clone({
setHeaders: {
Authorization: JWT,
}
});
}
return next.handle(newReq || req);
})
);
}
else {
return next.handle(req);
}
}
原来问题出在我的授权服务的getToken函数中。我忘记在返回令牌后完成可观察的!由于 httpClient.get observable 是通过我的 getToken observable 切换映射的,这导致我在 onDownloadClicked 中的订阅永远无法完成。
// from my auth service
getToken(resource: string): Observable<string> {
return Observable.create((observer: Observer<string>) => {
this.context.acquireToken(resource, (error, token) => {
if (token) {
observer.next(token);
observer.complete(); // this was missing
}
else {
this.login();
}
});
});
}