2015-11-19 1 views
1

Nouveau en programmation réactive. J'ai un flux, un flux de défilement, lié à un domNode, puis d'autres cours d'eau abonnées à travers un filtre:Comment puis-je filtrer un flux uniquement lorsqu'il change?

var element = document.getElementById('scrollableElement'); 
var sourceStream = Rx.Observable.fromEvent(element, 'scroll').map(function(e){ 
    return e.srcElement.scrollTop; 
}); 

var inTheOneHundreds = sourceStream 
    .filter(function (x, idx, obs) { 
    return x >= 100 && x < 200; 
    }); 

var inTheTwoHundreds = sourceStream 
    .filter(function (x, idx, obs) { 
    return x >= 200 && x < 300; 
    }); 

inTheOneHundreds.subscribe(function(value){ 
    console.log('one hundreds ' + value); 
}); 

inTheTwoHundreds.subscribe(function(value){ 
    console.log('two hundreds ' + value); 
}); 

Ce sorties comme:

one hundreds 193 
one hundreds 196 
one hundreds 199 
two hundreds 201 
two hundreds 204 

Vous pouvez le voir ici: http://jsbin.com/zedazapato/edit?js,console,output

Je veux que ces nouveaux flux de sortie lorsque les centaines changent (de true à false), plutôt que de sortir à plusieurs reprises:

one hundreds 199 
two hundreds 201 
one hundreds 170 
two hundreds 270 
one hundreds 103 
two hundreds 200 
one hundreds 156 

J'ai essayé d'utiliser Observable.distinctUntilChanged mais il ne semble pas se comporter comme je pense (il semble sortie la même chose): http://jsbin.com/gibefagiri/1/edit?js,console,output

Où vais-je tort?

Répondre

1

Vous avez plusieurs options.

Cela fera des flux à partir d'un prédicat, l'émission d'un élément lorsque le prédicat devient vrai:

var element = document.getElementById('scrollableElement'); 
var sourceStream = Rx.Observable.fromEvent(element, 'scroll').map(function(e){ 
    return e.srcElement.scrollTop; 
}); 

function whenBecomesTrue(stream, selector) { 
    return stream.distinctUntilChanged(selector).filter(selector); 
} 

var inTheOneHundreds = whenBecomesTrue(sourceStream, function (x, idx, obs) { 
    return x >= 100 && x < 200; 
}); 

var inTheTwoHundreds = whenBecomesTrue(sourceStream, function (x, idx, obs) { 
    return x >= 200 && x < 300; 
}); 

inTheOneHundreds.subscribe(function(value){ 
    console.log('one hundreds ' + value); 
}); 

inTheTwoHundreds.subscribe(function(value){ 
    console.log('two hundreds ' + value); 
}); 

Ou vous pouvez d'abord émettre des changements de page:

var element = document.getElementById('scrollableElement'); 
var sourceStream = Rx.Observable.fromEvent(element, 'scroll').map(function(e){ 
    return e.srcElement.scrollTop; 
}); 

function pageOf(x) { 
    return Math.floor(x/100); 
} 

var pageChanges = sourceStream.distinctUntilChanged(pageOf); 

var inTheOneHundreds = pageChanges.filter(function (x, idx, obs) { 
    return pageOf(x) === 1; 
}); 

var inTheTwoHundreds = pageChanges.filter(function (x, idx, obs) { 
    return pageOf(x) === 2; 
}); 

inTheOneHundreds.subscribe(function(value){ 
    console.log('one hundreds ' + value); 
}); 

inTheTwoHundreds.subscribe(function(value){ 
    console.log('two hundreds ' + value); 
}); 

Le problème avec votre approche à l'aide distinctUntilChanged est-il réellement différent de la valeur originale de scrollTop (qui diffère toujours de la valeur précédente), et non de la valeur booléenne indiquant si le nombre est dans la plage donnée.

+0

Merci pour votre inscription. Beaucoup plus clair. Je ne comprends pas très bien ton dernier commentaire. Est-il vrai que 'distinctUntilChanged' s'applique au flux source d'origine, plutôt qu'aux flux intermédiaires créés en utilisant' map' ou 'filter'? – sennett

+0

Non, cela s'applique certanly aux flux mappés et filtrés. Vous vous attendiez à ce qu'il distingue les valeurs 'true-false', mais il a séparé les nombres réels' 200,201,202 ... ', car c'est ce que le filtre renvoie. –