2017-07-01 5 views
2

J'essaie d'obtenir les 3 dernières valeurs émises, avec le code ci-dessous je m'attends à ce qu'après avoir peuplé uiOrder et appelé cancelOrderItem() pour quelques fois je peux avoir accès aux 3 dernières révisions de l'ordre avec getHistory(), mais je reçois en fait la dernière valeur (actuelle) 3 fois, j'ai essayé replaySubject (3) avec les mêmes résultats. voici mon code:Rx.js ne peut pas dépasser les valeurs

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); 
    } 

} 

ce que je fais mal?

Répondre

3

L'opérateur que vous recherchez est bufferCount(3,1) qui crée une fenêtre glissante des 3 dernières valeurs émises. Inconvénient: il commencera seulement à émettre après que 3 valeurs aient été accumulées. Si vous voulez avoir la première valeur que vous pouvez faire quelque chose comme ceci:

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

De cette façon, votre diagramme de marbre se présente comme suit:

---Order1-----------------Order2--------------------Order3 
bufferCount(3,1) 
---[null,null,Order1]-----[null,Order1,Order2]------[Order1,Order2,Order3] 
-1
getHistory() { 
this.uiOrder.takeLast(3).subscribe((res) => { 
    console.log('uiOrder', res); 
}).unsubscribe() } 

takeLast opérateur récupère   les trois dernières valeurs émises par la source observable.

+1

Merci, mais takeLast (n) émettra les dernières valeurs de n seulement après la source est terminée et ce n'est pas le comportement que je cherche. –

1

Vous risquez de trop y penser. Si vous avez besoin des 3 dernières commandes disponibles à tout moment, pourquoi ne pas les stocker dans un tableau mis à jour chaque fois que uiOrder émet une nouvelle commande?

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) 
); 

Maintenant, chaque fois que vous voulez connaître les plus récentes 3 commandes, il suffit de regarder orderHistory. En prime, cette recherche est une opération synchrone.

+1

J'ai réfléchi à cette approche, mais les Observables n'ont-ils pas pour but de fournir des valeurs dans le temps? –

+0

@MoshikHasky J'ai d'abord écrit une réponse en utilisant simplement Observables mais j'ai changé d'avis car elle était inutilement complexe - elle utilisait un flux secondaire qui regardait le premier et utilisait le ['scan'] (https: //www.learnrxjs Opérateur .io/opérateurs/transformation/scan.html) pour suivre et émettre les 3 dernières commandes dans un tableau chaque fois que la source a émis un nouvel ordre. Parce que c'est une approche beaucoup plus simple, plus facile à lire et à déboguer, je pense que c'est supérieur. Pour ne pas mentionner moins de ressources car il n'y a pas besoin d'installer de nouveaux objets, de nouveaux flux, de nouveaux observateurs ... – BeetleJuice

+0

Je vais marquer votre réponse, mais juste pour mes observables mieux comprendre, pouvez-vous partager comment un morceau de code avec scan ressemblera? –