【问题标题】:Rx.js can't get past valuesRxjs 无法获取过去的值
【发布时间】:2017-07-01 08:35:49
【问题描述】:

我正在尝试获取发出的最后 3 个值,下面的代码我希望在填充 uiOrder 并调用 cancelOrderItem() 几次之后,我可以使用 getHistory() 访问订单的最后 3 个修订,但是我实际上得到了最后一个(当前)值 3 次,我尝试了 replaySubject(3) 具有相同的结果。 这是我的代码:

export class OrdersService {

  public readonly orders: Observable<Order[]>;
  public readonly uiOrder: Observable<Order>;

  private _orders: BehaviorSubject<Order[]>;
  private _uiOrder: BehaviorSubject<Order>;

  private dataStore: {
    uiOrder: Order,
    orders: Order[]
 };


  constructor() {

    this.dataStore = {
      uiOrder: null,
      orders: []
    };

    this._orders = <BehaviorSubject<Order[]>>new BehaviorSubject([]);
    this._uiOrder = <BehaviorSubject<Order>>new BehaviorSubject({});
    this.orders = this._orders.asObservable();
    this.uiOrder = this._uiOrder.asObservable();
  }

  getOrder(orderId: number | string) {
    for (let i = 0; i < this.dataStore.orders.length; i++) {
      if (this.dataStore.orders[i].id == orderId) {
        this.dataStore.orders[i].lastAccess = moment().format().slice(0, 19) + 'Z';
        this.dataStore.uiOrder = this.dataStore.orders[i];
        this.updateUiOrder();
      }
    }
  }


  cancelOrderItem(action) {
    this.dataStore.uiOrder.sections[action.sectionIndex].orderDetails.splice(action.orderDetailsIndex, 1);
    this.updateUiOrder()
  }

  getHistory() {
    this.uiOrder.take(3).subscribe((res) => {
      console.log('uiOrder', res);
    }).unsubscribe()
  }

  updateUiOrder() {
    console.log('updating ui order');
    this._uiOrder.next(this.dataStore.uiOrder);
  }

}

我做错了什么?

【问题讨论】:

    标签: angular typescript rxjs5


    【解决方案1】:

    您要查找的运算符是bufferCount(3,1),它会创建一个包含最后发出的 3 个值的滑动窗口。缺点:它只会在累积 3 个值后开始发射。如果你想拥有第一个值,你可以这样做:

    Rx.Observable.from([null,null])
      .concat(this.uiOrder)
      .bufferCount(3,1)
      .subscribe(uiOrderHistory => ... );
    

    这样您的大理石图将如下所示:

    ---Order1-----------------Order2--------------------Order3
    bufferCount(3,1)
    ---[null,null,Order1]-----[null,Order1,Order2]------[Order1,Order2,Order3]
    

    【讨论】:

      【解决方案2】:

      你可能想多了。如果您需要随时可用的最近 3 个订单,为什么不将它们存储在一个数组中,每次uiOrder 发出新订单时都会更新?

      orderHistory:Order[] = [];
      
      orders$ = this.uiOrder.subscribe(order =>
         let h = this.orderHistory;
         //add the order to history array:
         h = [...h, order];
         //splice the array to keep only the last 3 orders:
         if (h.length > 3) h.splice(0,h.length-3)
      );
      

      现在,当您想知道最近的 3 个订单时,只需查看orderHistory。作为奖励,该查找是一个同步操作。

      【讨论】:

      • 我考虑过这种方法,但 Observables 的意义不在于随着时间的推移提供值吗?
      • @MoshikHasky 我最初只使用 Observables 写了一个答案,但后来我改变了主意,因为它不必要地复杂——它使用了一个二级流来观看第一个流,并使用 scan 运算符来跟踪并在每次源发出新订单时发出数组中的最后 3 个订单。因为这是一种更简单、更易于阅读和调试的方法,所以我认为它更胜一筹。更不用说更少的资源消耗,因为不需要设置新对象、新流、新观察者......
      • 我会标记你的答案,但只是为了更好地理解 Observables,你能分享一段带有扫描的代码的样子吗?
      • @MoshikHasky @MarkvanStraten 的答案是全可观察的,比我最初写的更优雅!我不知道他演示的bufferCount 运算符
      【解决方案3】:
      getHistory() {
      this.uiOrder.takeLast(3).subscribe((res) => {
        console.log('uiOrder', res);
      }).unsubscribe()  }
      

      takeLast 运算符检索源 observable 发出的最后三个值。

      【讨论】:

      • 谢谢,但是 takeLast(n) 只会在源代码完成后发出最后 n 个值,这不是我正在寻找的行为。
      猜你喜欢
      • 2016-02-05
      • 2013-12-05
      • 2022-01-09
      • 1970-01-01
      • 2020-09-28
      • 2019-08-23
      • 2021-02-20
      • 1970-01-01
      • 2021-04-14
      相关资源
      最近更新 更多