Search code examples
functional-programmingreactive-programmingrxjsfrpbacon.js

Wait for latest values from dependent streams in BaconJS?


I have 3 streams. gradingResult and contextId depend on studentResponse. I need to fire an event and only one event (otherwise, this is trivial) when all 3 have the latest values.

I've tried #combineTemplate and #sampledBy studentResponse. Unfortunately, I always see the wrong data---gradingResult and contextId have the old values in the combined template. How can I wait for all streams to have the latest values?

Code is shown below:

var studentResponse = new Bacon.Bus();
var gradingResult = new Bacon.Bus();
var contextId = new Bacon.Bus();

studentResponse.onValue(function(f) {
   gradingResult.push(f);
   contextId.push(f);
});

Bacon.combineTemplate({
  studentResponse: studentResponse,
  gradingResult: gradingResult,
  contextId: contextId
}).sampledBy(studentResponse)
  .onValue(function(t) {
    console.log(t);
});

studentResponse.push(1);
studentResponse.push(2);
studentResponse.push(3);

Link to jsfiddle: https://jsfiddle.net/3o4c9sm8/1/

UPDATE: this is a contrived example. In the real code, gradingResult is an ajax request. Both gradingResult and contextId have time dependencies on studentResponse


Solution

  • The solution is to sample by the stream that updates last. In this case, it's contextId. Changing the code to the following makes it work:

    var studentResponse = new Bacon.Bus();
    var gradingResult = new Bacon.Bus();
    var contextId = new Bacon.Bus();
    
    studentResponse.onValue(function(f) {
      gradingResult.push(f);
      contextId.push(f);
    });
    
    Bacon.combineTemplate({
     studentResponse: studentResponse,
     gradingResult: gradingResult,
     contextId: contextId
    }).sampledBy(contextId) //Sampling by stream that updates last <---
    .onValue(function(t) {
      console.log(t);
    });
    
    studentResponse.push(1);
    studentResponse.push(2);
    studentResponse.push(3);