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:
- Go thru each check. A
check
contains anid
andstatus
= fail/pass/pending. If pending, it contains a list ofobservables
.- If status = pass, then return the id (you're done!)
- if status = fail, then try the next check
- if status = pending
- try each observable in order
- if observable result is 'false', then try the next check
- if reach end of observable list and result is 'true', then return the id (you're done!)
- try each observable in order
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 replaceflatMap
withflatMapConcat
.