如何从Nativescript Angular中的另一个Observable上的reduce操作中获取Observable <number>?

时间:2018-11-15 13:09:15

标签: angular typescript reduce

我试图在我的角度分量中显示一个可观察的总数

total$ | async

它应该是购物篮中所有行的计算总和:

totalAmount = sum of (price * unitsOrdered)

我的界面是:

export interface IBasketLine {
    unitsOrdered?: number;
    price?: number;
}
export interface IBasket {
    header?: IBasketHeader;
    lines?: Array<IBasketLine>;
}

我的Angular组件包含 2个可观察对象

basket$: Observable<IBasket>;
nettoTotal$: Observable<number>;

可观察的篮子$是从我的ngrx商店初始化的,所有行在我的视图中都是可见的。这是我的 ngOnInit 函数:

ngOnInit(): void {

   this.store.dispatch(new basketActions.Load());

    this.basket$ = this.store.pipe(
        select(fromBasket.getBasket)
    );

    this.nettoTotal$ = this.basket$.pipe(
        map((basket) => basket.lines),
        reduce( ??? )
    );
}

如何使用reduce函数,以便在视图中获得正确的总数?

更新:

这确实起作用:

this.nettoTotal$ = this.basket$.pipe(
  map((basket) => {
     if (basket) {
        return basket.lines;
     } else {
        return [];
     }
  }),
  map((lines) => {
            let total = 0;
            for (const line of lines) {
                const val = Math.round((line.bestelaantal * line.nettoprijs * 100) / 100);
                total = total + val;
            }

            return total;
        })
    );

更新2:

当我直接调用服务的方法并返回Observable的IBasket时,此代码有效:

this.nettoTotal$ = this.basketService.getBasket().pipe(
            map((basket) => basket.lines),
            map((lines) => lines.map((line) => line.nettoprijs * line.bestelaantal).reduce(
                (accumulator, linePrice) => accumulator + linePrice,
                0
            ))
        );

当我使用来自商店的可观察物时,此代码不起作用:

this.nettoTotal$ = this.basket$.pipe(
            map((basket) => basket.lines),
            map((lines) => lines.map((line) => line.nettoprijs * line.bestelaantal).reduce(
                (accumulator, linePrice) => accumulator + linePrice,
                0
            ))
        );

3 个答案:

答案 0 :(得分:0)

RxJs的reduce函数的作用类似于Array.prototype.reduce函数。您为它提供了一个处理reduce和seed值的函数,当Observable完成时,该reduced值将从流中发出。这是您计算总和的方法:

this.nettoTotal$ = this.basket$.pipe(
  map((basket) => basket.lines),
  reduce((total, count) => total + count, 0)
);

答案 1 :(得分:0)

由于您的map返回行,并且每行将包含unitsOrderedprice,因此您可以引入另一轮map并直接返回{{1} } * price,然后在unitsOrdered运算符中进行累加。

尝试一下:

reduce

这是您推荐的Sample StackBlitz

答案 2 :(得分:0)

我终于亲自找到了问题。它完全与reduce运算符无关。目前,我执行了reduce函数,该篮子的数据尚未从后端获取。换句话说,商店尚未从我的LoadSuccess操作接收数据。
因此,我最终在我的减速器中添加了一个新的选择器来计算netTotal。

export const getNetTotal = createSelector(
    getBasketFeatureState,
    (state) => {
        if (!state.basket) {
            return 0;
        }
        let total = state.basket.lines.map((line) => (line.amountOrdered * line.price)).reduce(
            (total, amount) => total + amount,
            0
        );
        total = Math.round(total * 100) / 100;

        return total;
    }
);

ngOnInit函数现在看起来像这样,一切正常:

this.store.dispatch(new basketActions.Load());

this.basket$ = this.store.pipe(select(fromBasket.getBasket));
this.nettoTotal$ = this.store.pipe(select(fromBasket.getNetTotal));