I'm trying to do this relatively complex operation in BaconJs.
Basically, the idea is keep trying each check
until you have a 'pass' status or they all fail. The catch is that 'pending' statuses have a list of Observables (built from jquery ajax requests) that will resolve the check. For performance reasons, you need to try each Observable in order until either they all pass or one fails.
Here's the full pseudo algorithm:
check
contains an id
and status
= fail/pass/pending. If pending, it contains a list of observables
.
Here's the Bacon code. It doesn't work when the Observables are Ajax requests. Basically, what happens is that it skips over pending checks....it doesn't wait for the ajax calls to return. If I put a log() right before the filter(), it doesn't log pending requests:
Bacon.fromArray(checks)
.flatMap(function(check) {
return check.status === 'pass' ? check.id :
check.status === 'fail' ? null :
Bacon.fromArray(check.observables)
.flatMap(function(obs) { return obs; })
.takeWhile(function(obsResult) { return obsResult; })
.last()
.map(function(obsResult) { return obsResult ? check.id : null; });
})
.filter(function(contextId) { return contextId !== null; })
.first();
UPDATE: the code works when the checks look like this: [fail, fail, pending]. But it doesn't work when the checks look like this: [fail, pending, pass]
I agree with @paulpdaniels Rx-based answer. The problem seems to be that when using flatMap
, Bacon.js won't wait for your first "check-stream" to complete before launching a new one. Just replace flatMap
with flatMapConcat
.