如何从 Observable 中 return Imagebitmaps 数组
How to return an array of Imagebitmaps from within an Observable
我需要从一组 URL 创建一个 Imagebitmaps 的数组。 HTTP 请求应该与取消请求数组的能力并行完成,例如如果提供了一组新的 URL。
收到每个图像 blob 后,应将其转换为 Imagebitmap,并在将所有 Imagebitmap 作为数组返回给订阅者之前进行一些额外处理。
到目前为止我有这个:
this.nextImagesSubscription = this.nextImagesSubject.pipe(switchMap((urls: string[]) => {
console.log(`received new images`)
return forkJoin(urls.map((url, index) => this.beService.getImageBlob(url).pipe(map(blob => ({blob, url, index})))))
})).subscribe((blobData: {blob: Blob, url: string, index: number}[]) => {
console.log(`Received blobs: ${blobData.length}`);
blobData.forEach(image => console.log(`${image.index}: '${image.url}'`))
})
以上代码满足:
- 并行 HTTP 请求
- 可以取消 HTTP 请求(在调用
nexImagesSubject.next()
时)
- 所有数据都作为数组返回给订阅者。
然而它不满足:
- Return
Imagebitmap
的数组
- 不允许在收到后对 Blob 数据进行额外处理,即转换为
ImageBitmap
。
创建 Imagebitmap 很简单,但导致我出现问题的是对 Promise 的处理。例如:
return forkJoin(urls.map((url, index) => this.beService.getImageBlob(url)
.pipe(map(blob => {
createImageBitmap(blob).then(image => {
/* Do some additional compute on image */
return ({image, url, index})});
}))))
这不起作用,因为它不是从 map
返回的 {image, url, index}
。
如何在 pipe
中创建 Imagebitmap 并将所有 Imagebitmap 作为数组返回给订阅者(并满足上述其他要求)?
每个 url / 图片你有很多工作要做。我建议在这样的方法中定义所有每个 url 操作:
private async loadImageBitmap(url: string): Promise<ImageBitmap> {
// Step 1: Load the blob for the single specified url.
const blob = await this.beService.getImageBlob(url).toPromise();
// Step 2: Create the ImageBitmap.
const image = new ImageBitmap();
// Step 3: Perform additional processing.
/* Do some additional compute on image */
return image;
}
有了这个指定,管道看起来更干净,更易读:
this.nextImagesSubscription = this.nextImagesSubject.pipe(
map(urls => urls.map(url => this.loadImageBitmap(url))),
switchMap(requests => combineLatest(requests))
).subscribe(images => {
/* Do what ever you want with the images */
});
我唯一不确定的是取消部分:既不在我的代码中,也不在你的代码中。我不认为 http 请求会在另一组 url 发出时被取消。
要处理图像,您可以创建一个接受 Blob 和 returns ImageBitmap 的异步函数,例如:
async function processImage(blob: Blob): Promise<ImageBitmap> {
const imageBitmap = await createImageBitmap(blob);
//image post process ...
return imageBitmap;
}
然后在您的 forkJoin
中使用 from
围绕函数调用的 Promise 创建一个 Observable。
return forkJoin(
urls.map((url, index) =>
this.beService.getImageBlob(url).pipe(
switchMap(blob => from(processImage(blob))),
map(image => ({ image, url, index })) //<- Only required if you want to export also the url and index
)
)
)
干杯
我需要从一组 URL 创建一个 Imagebitmaps 的数组。 HTTP 请求应该与取消请求数组的能力并行完成,例如如果提供了一组新的 URL。
收到每个图像 blob 后,应将其转换为 Imagebitmap,并在将所有 Imagebitmap 作为数组返回给订阅者之前进行一些额外处理。
到目前为止我有这个:
this.nextImagesSubscription = this.nextImagesSubject.pipe(switchMap((urls: string[]) => {
console.log(`received new images`)
return forkJoin(urls.map((url, index) => this.beService.getImageBlob(url).pipe(map(blob => ({blob, url, index})))))
})).subscribe((blobData: {blob: Blob, url: string, index: number}[]) => {
console.log(`Received blobs: ${blobData.length}`);
blobData.forEach(image => console.log(`${image.index}: '${image.url}'`))
})
以上代码满足:
- 并行 HTTP 请求
- 可以取消 HTTP 请求(在调用
nexImagesSubject.next()
时) - 所有数据都作为数组返回给订阅者。
然而它不满足:
- Return
Imagebitmap
的数组
- 不允许在收到后对 Blob 数据进行额外处理,即转换为
ImageBitmap
。
创建 Imagebitmap 很简单,但导致我出现问题的是对 Promise 的处理。例如:
return forkJoin(urls.map((url, index) => this.beService.getImageBlob(url)
.pipe(map(blob => {
createImageBitmap(blob).then(image => {
/* Do some additional compute on image */
return ({image, url, index})});
}))))
这不起作用,因为它不是从 map
返回的 {image, url, index}
。
如何在 pipe
中创建 Imagebitmap 并将所有 Imagebitmap 作为数组返回给订阅者(并满足上述其他要求)?
每个 url / 图片你有很多工作要做。我建议在这样的方法中定义所有每个 url 操作:
private async loadImageBitmap(url: string): Promise<ImageBitmap> {
// Step 1: Load the blob for the single specified url.
const blob = await this.beService.getImageBlob(url).toPromise();
// Step 2: Create the ImageBitmap.
const image = new ImageBitmap();
// Step 3: Perform additional processing.
/* Do some additional compute on image */
return image;
}
有了这个指定,管道看起来更干净,更易读:
this.nextImagesSubscription = this.nextImagesSubject.pipe(
map(urls => urls.map(url => this.loadImageBitmap(url))),
switchMap(requests => combineLatest(requests))
).subscribe(images => {
/* Do what ever you want with the images */
});
我唯一不确定的是取消部分:既不在我的代码中,也不在你的代码中。我不认为 http 请求会在另一组 url 发出时被取消。
要处理图像,您可以创建一个接受 Blob 和 returns ImageBitmap 的异步函数,例如:
async function processImage(blob: Blob): Promise<ImageBitmap> {
const imageBitmap = await createImageBitmap(blob);
//image post process ...
return imageBitmap;
}
然后在您的 forkJoin
中使用 from
围绕函数调用的 Promise 创建一个 Observable。
return forkJoin(
urls.map((url, index) =>
this.beService.getImageBlob(url).pipe(
switchMap(blob => from(processImage(blob))),
map(image => ({ image, url, index })) //<- Only required if you want to export also the url and index
)
)
)
干杯