Angular 18 组件无法按预期与 blob 一起工作

问题描述 投票:0回答:1

我有一个 Angular 18 项目,它从 API 中提取图像数据并将其显示在屏幕上。有人可以帮助我理解这种行为吗?

应用程序在 ImageService.ts 的 getImage(..) 函数中使用“const a = document.createElement('a');”抛出异常“文档未定义 文件。即使出现此错误,应用程序也会提取图像数据并将其绘制在页面上。

enter image description here

当我取出这条线时,我收到了不同的错误,并且图像也没有显示。

enter image description here

我在 API 上添加了一个断点,还在 ImageService.ts 中的 getImage 函数上添加了一个断点,当我刷新页面时,服务器 API 断点甚至在 getImage 函数中的断点之前被命中。

是否有一种新的方式来服务 Observable 或者这可能是与角度钩子相关的问题?

图像服务.ts

@Injectable({
  providedIn: 'root'
})
export class ImageService {

  private apiUrl = 'http://localhost:5189/LoadImage'; 

  constructor(private http: HttpClient) { }

  getImage(objectId: string): Observable<Blob> {
    const a = document.createElement('a');  
    return this.http.get(`${this.apiUrl}/${objectId}`, {responseType: 'blob' });
  }
}

图像.component.ts

@Component({
  selector: 'app-image',
  templateUrl: './image.component.html',
  styleUrls: ['./image.component.css'],
  standalone: true,
  imports:[CommonModule]
})
export class ImageComponent implements OnInit {
  imageUrl: any;

  constructor(private imageService: ImageService) {}

  async ngOnInit(): Promise<void> {
      (await this.imageService.getImage('apple')).subscribe({
        next: (blob) => {              
          const objectURL = URL.createObjectURL(blob);  
          this.imageUrl = objectURL;
        }}
      );
    }
  }
}

Image.component.html:

<div>
    <img [src]="imageUrl" alt="Image" />
</div>

App.component.html

<app-image></app-image>
angular typescript angular-components angular18
1个回答
0
投票

在服务器上,

document
window
对象并不像浏览器中那样存在,因此涉及这些对象的某些功能将无法工作。

createObjectUrl 似乎与

document
window
对象相关联,因此问题正在发生。


要解决这个问题,您必须确保此逻辑仅在浏览器上执行。


我们为此提供了两种工具。

当我们只想在浏览器上渲染 HTML 时,可以使用

defer

当我们只想在浏览器上运行组件代码时,可以使用

afterNextRender


因此您可以将代码更新为。

@Component({
  selector: 'app-image',
  templateUrl: './image.component.html',
  styleUrls: ['./image.component.css'],
  standalone: true,
  imports: [CommonModule],
})
export class ImageComponent implements OnInit {
  imageUrl: any = 'https://placehold.co/600x400'; // show some loading image here!

  constructor(private imageService: ImageService) {}

  ngOnInit() {
    afterNextRender(() => this.loadImage()); // runs only on browser
  }

  loadImage() {
    this.imageService.getImage('apple').subscribe({
      next: (blob: Blob) => {
        const objectURL = URL.createObjectURL(blob);
        this.imageUrl = objectURL;
      },
    });
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.