嵌套的Observable/Promise(尝试在mapper函数中阻止/等待流) [英] Nested Observable/Promise (trying to block/wait flow in mapper function)

查看:63
本文介绍了嵌套的Observable/Promise(尝试在mapper函数中阻止/等待流)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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 the forkJoin completes
  • Return the serviceModels in a mapTo

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆