如何在高阶可观察物中返回外部可观察物而不是内部

时间:2020-10-27 10:59:34

标签: javascript angular rxjs observable

让我们用以下代码澄清问题:

    this.rates$ = this._glbRateService.getRates(params); // 1
    this.rates$.pipe(
        mergeMap(rates => {
            const priceByRates: Observable<any>[] = rates.map(rate => {
                const paramsRatingItemProduct = {
                    idItem: product.idItem,
                    idRate: rate.idRate
                };
                return this._glbRatingItemProduct.getPrice(paramsRatingItemProduct); // 2
            });
            return priceByRates;
        })
    ).subscribe(response => {
        console.log(response); // 3
    });

在该代码中:

  1. 我从服务器获得费率
  2. 每一种价格,我都会得到价格(地图)
  3. 我的console.log从内部订阅中返回值(this._glbRatingItemProduct.getPr ...)

我想要的是对映射值和内部订阅进行逻辑处理。

类似这样的东西:

this.rates$ = this._glbRateService.getRates(params);
this.rates$.pipe(
    mergeMap(rates => {
        const priceByRates: Observable<any>[] = rates.map(rate => {
            const paramsRatingItemProduct = {
                idItem: product.idItem,
                idRate: rate.idRate
            };
            return this._glbRatingItemProduct.getPrice(paramsRatingItemProduct);
            // WITH THE SUBSCRIPTION OF THIS RETURN I WANT TO MAKE LOGIC
            // WITH rates.map, and then return rates, NOT THE INNER SUBSCRIPTION

        });
        return priceByRates;
    })
).subscribe(response => {
    console.log(response);
});

2 个答案:

答案 0 :(得分:1)

您首先需要先使用forkJoin执行内部可观察数组 然后使用数组运行映射功能

mergeMap(rates => {
    const priceByRates: Observable<any>[] = rates.map(rate => {
        const paramsRatingItemProduct = {
            idItem: product.idItem,
            idRate: rate.idRate
        };
        return this._glbRatingItemProduct.getPrice(paramsRatingItemProduct);

    });
    return forkJoin(...priceByRates).pipe((values)=>values.map....your logic ));
})

https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin

答案 1 :(得分:1)

分离映射和展平高阶可观察对象的逻辑有时会很有帮助。这里应该更清楚一点,$val = 'hello_world_again'; $val = str_replace('_','',ucwords($val,'_')); echo $val; //HelloWorldAgain 返回一组可观察对象,而map()将所有这些可观察对象连接到一个流中。

forkJoin()

另一方面,this.rates$ = this._glbRateService.getRates(params); this.rates$.pipe( map(rates => rates.map( rate => this._glbRatingItemProduct.getPrice({ idItem: product.idItem, idRate: rate.idRate }) ), mergeMap(priceByRates => forkJoin(priceByRates)) ).subscribe(console.log); 仅在所有源可观测对象完成后才发射。如果不需要所有响应,则可以使用简单的forkJoin()使源流解耦。只需更改一行:

merge()

要记住的事情是mergeMap(priceByRates => merge(...priceByRates)) 期望返回单个流。它将数组转换为值流。因此,mergeMap不会将mergeMap(num => [10,9,8,7,num])映射到一个数组中,它会创建一个新的流,该流将一次发出一个数字。

这就是为什么num一次只发出每个可观察到的(作为高阶可观察到的)的原因。

有了这些知识,您实际上可以将流更改为合并,而无需使用上面的静态合并功能。看起来可能像这样:

mergeMap(_ => val : Observable[])

mergeAll()会在到达每个高阶时将其视为可观察到的内容,并订阅并合并其输出。