Javascript 角度HttpClient可观察到未完成
我有以下代码:Javascript 角度HttpClient可观察到未完成,javascript,angular,rxjs,observable,angular-httpclient,Javascript,Angular,Rxjs,Observable,Angular Httpclient,我有以下代码: // 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()
// 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!');
}
);
}
//在服务中
downloadCSV():可观察{
返回这个.httpClient.get(`${apirl}/a.csv`,{responseType:'blob'});
}
//组件中
onDownloadClicked(事件:MouseeEvent){
this.downloading=true;
this.service.downloadCSV()
.pipe(finalize(()=>this.downloading=false))
.订阅(
(数据:Blob)=>{
控制台日志(数据);
},
(错误)=>{
控制台错误(error);
警报('抱歉,有问题。请重试');
},
() => {
console.log('completed!');
}
);
}
数据记录正确,但“已完成!”不会记录,也不会调用finalize
编辑:
因此,在进一步的调查中,问题似乎与添加auth头的拦截器有关
如果拦截器被绕过(并且在服务器上禁用了身份验证),则可观察对象将无误地完成
我不明白为什么会这样。可能与请求被克隆的事实有关
//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);
}
}
//拦截器代码
截取(req:HttpRequest,next:HttpHandler):可观察{
let范围:字符串;
//仅为以下作用域注入令牌
如果(请求url.indexOf('https://graph.microsoft.com') === 0) {
范围=https://graph.microsoft.com';
}
else if(请求url.indexOf('https://management.azure.com') === 0) {
范围=https://management.azure.com';
}
else if(req.url.indexOf(environment.apiUrl)==0){
scope=environment.appId;
}
如果(范围){
返回此.authService.getToken(scope.pipe)(
开关映射((令牌)=>{
让newReq;
如果(令牌){
const JWT=`Bearer${token}`;
newReq=req.clone({
集合标题:{
授权:JWT,
}
});
}
返回next.handle(newReq | | req);
})
);
}
否则{
返回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();
}
});
});
}
//来自我的身份验证服务
getToken(资源:字符串):可观察{
返回可观察的。创建((观察者:观察者)=>{
this.context.acquireToken(资源,(错误,标记)=>{
如果(令牌){
下一个(令牌);
observer.complete();//缺少此项
}
否则{
this.login();
}
});
});
}
无法在本地复制-当使用{responseType:'blob'}
和管道中的finalize
创建HttpClient#get
时,我看到已完成的回调被调用。按F12并告诉我们网络上有什么。你看到了什么反应?我试图制造一场闪电战。使用了所有库的相同版本,但我也不能复制它。它只在sb中起作用:@JohnPeters网络选项卡看起来很正常,请求代码为200,内容看起来很好。