Angular 4加载图片时出现null请求问题求助
解决Angular 4中自定义Image管道+async导致的null请求问题
嘿,这个http://localhost:4200/null的无效请求我之前也碰到过,本质原因其实很明确:async管道在Observable还没吐出第一个值的时候,会返回null,而Angular的[src]绑定会把这个null直接赋值给img的src属性,浏览器就会把null解析成当前域名下的路径,于是就出现了这个莫名其妙的请求。
下面给你几个靠谱的解决办法,你可以按需选择:
方法一:延迟渲染img直到异步流有值
用ng-container先订阅异步结果,拿到有效的图片地址后再渲染img标签,从根源上避免src被设置为null:
<div class="card-avatar" (click)="openFilePicker()"> <!-- 先拿到异步返回的图片地址 --> <ng-container *ngIf="(imageLink | image) | async as imageSrc"> <img class="img pointer" [ngStyle]="{'width.px': 130,'height.px': 130}" *ngIf="links.avatar && imageLink" [src]="imageSrc" /> </ng-container> <img src="../../assets/img/default-avatar.png" class="img pointer" *ngIf="links.avatar === undefined"> </div>
这样img标签只有在拿到真实的base64地址后才会被渲染,完全不会触发null请求。
方法二:给管道的Observable添加初始空值
在管道返回的Observable上加上startWith('')操作符,让async管道一开始就拿到空字符串(而不是null),空字符串的src不会触发浏览器的请求:
首先要导入startWith操作符:
import { startWith } from 'rxjs/operators';
然后修改管道的返回逻辑:
return this.http.get(url, new RequestOptions({headers: headers, responseType: ResponseContentType.Blob})) .map(response => response.blob()) .switchMap(blob => { return Observable.create(observer => { const reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { observer.next(reader.result); observer.complete(); // 别忘了调用complete,避免内存泄漏 } }); }) .pipe(startWith('')); // 新增这一行,给Observable一个初始空值
方法三:提前校验管道的输入参数
在管道的transform方法开头,先检查传入的url是否有效,如果是空值直接返回一个空的Observable,避免无效的http请求:
transform(url: string, selfLink?: any, width?: any) { // 先校验url,无效直接返回空值Observable if (!url) { return Observable.of(''); } // 下面是你原来的逻辑 if (selfLink) { url = selfLink + url + width; } const headers = new Headers({'Authorization': 'Bearer ' + localStorage.getItem('token'), 'Content-Type': 'image/jpeg'}); return this.http.get(url, new RequestOptions({headers: headers, responseType: ResponseContentType.Blob})) // ... 剩下的逻辑不变 }
另外还有两个小建议:
- 你现在用的是Angular 4的
Http服务,其实官方已经推荐使用HttpClient了,它处理响应类型的方式更简洁,后续可以考虑升级替换。 - 管道里直接用
localStorage.getItem('token')不太符合Angular的依赖注入规范,建议把token的获取封装成一个Auth服务,这样更便于测试和维护。
内容的提问来源于stack exchange,提问作者Alessandro Celeghin
相关产品推荐
相关产品推荐

