嵌套的Observable/Promise(尝试在mapper函数中阻止/等待流) [英] Nested Observable/Promise (trying to block/wait flow in mapper function)
问题描述
我在Angular应用中有以下代码:
服务$.管道(map(serviceModels => {serviceModels.forEach((srv,srvIdx)=> {//解析服务中的图像srv.images.forEach(async(img,imgIdx)=> {serviceModels [srvIdx] .images [imgIdx] =等待this.imageSrv.resolveImage(img).toPromise();});});返回serviceModels;});[...]
结果是一次发射,之后发生一个值更改.
emit-> service.image [0]//'unrendered-url'->(wait)-> service.image [0]//correct-url/image-path
我正在尝试从服务(this.imageSrv)解析图像,该服务采用字符串并返回带有呈现字符串的observable/promise.我想要的只是阻止代码(或将map()保留发射,直到图像解析),因为我在Angular中为 services [0] .images [0]
.<获得了两个值./p>
最简单的方法是将诺言放入 service [0] .images
数组和 img |异步
在模板引擎中,但是我想避免这种情况,并可能学习一些新知识.
您当前正在尝试在 map
内运行新的可观察对象-用于将可观察对象的结果同步转换为其他结果结构体.我将忽略等待诺言的尝试,因为将通过直接使用基础可观察对象来解决.
我要采用的方法:
- 使用
switchMap
将内部可观察对象链接到外部可观察对象 - 展平嵌套的图像数组
- 从展平的图像数组创建可观察对象数组
- 在
forkJoin
中运行可观察数组 - forkJoin 完成后,在
serviceModels
中更新解析的图像 - 在
mapTo
中返回
serviceModels
services $ .pipe(switchMap(serviceModels => {//展平图像const images = serviceModels.reduce((acc,srv)=> acc.concat(srv.images),[]);//映射到可观察对象数组const observables = images.map(img => this.resolveImage(img));//并行运行可观察对象返回forkJoin(observables).pipe(点击(图片=> {//遍历原始嵌套数组//从展平的图像结果中提取图像让flatIdx = 0;serviceModels.forEach(srv => {srv.images.forEach((img,imgIdx)=> {srv.images [imgIdx] = images [flatIdx ++];});});}),//从外部可观察到的返回serviceModelsmapTo(serviceModels))}))[...]
顺便说一句,我建议不要用已解析的图像覆盖原始图像.虽然这是有效的Javascript,但是如果您使用类型,则会遇到Typescript的问题(而且我看不出有任何理由不这样做).
演示: https://stackblitz.com/edit/angular-a6fblk >
I have the following code in an Angular app:
services$
.pipe(
map(serviceModels => {
serviceModels
.forEach((srv, srvIdx) => {
// Resolve images in services
srv.images.forEach(async (img, imgIdx) => {
serviceModels[srvIdx].images[imgIdx] = await this.imageSrv.resolveImage(img).toPromise();
});
});
return serviceModels;
});
[...]
Result is a single emition with one value change afterwards.
emit -> service.image[0] // 'unrendered-url' -> (wait) -> service.image[0] // correct-url/image-path
I'm trying to resolve the image from a service (this.imageSrv) that takes a string and returns a observable/promise with a rendered string. All I want is the code to block (or map() to hold the emition until the images are resolved) because I get two values in Angular for the services[0].images[0]
.
The easy way out is to put promises in the service[0].images
array and img | async
in the template engine, but I'd like to avoid that and maybe learn something new.
You're currently trying to run new observables inside a map
- which is for synchronously transforming the result of an observable into a different structure. I will ignore the attempt to await the promise, as that will be addressed by using the underlying observables directly.
The approach I'm going to take:
- Use
switchMap
to chain an inner observable to the outer observable - Flatten the nested image arrays
- Create an array of observables from the flattened image array
- Run the observable array in a
forkJoin
- Update the resolved images in the
serviceModels
when theforkJoin
completes - Return the
serviceModels
in amapTo
services$.pipe(
switchMap(serviceModels => {
// flatten images
const images = serviceModels.reduce((acc, srv) => acc.concat(srv.images), []);
// map to array of observables
const observables = images.map(img => this.resolveImage(img));
// run observables in parallel
return forkJoin(observables).pipe(
tap(images => {
// loop over original nested arrays
// extract image from flattened images result
let flatIdx = 0;
serviceModels.forEach(srv => {
srv.images.forEach((img, imgIdx) => {
srv.images[imgIdx] = images[flatIdx++];
});
});
}),
// return serviceModels from the outer observable
mapTo(serviceModels)
)
})
)
[...]
By the way, I would recommend not overwriting the original images with the resolved images. While this is valid Javascript, you'll run into issues with Typescript if you're using types (and I don't see any reason not to).
DEMO: https://stackblitz.com/edit/angular-a6fblk
这篇关于嵌套的Observable/Promise(尝试在mapper函数中阻止/等待流)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!