Frage

I have this:

var bulk = array[1,2,3,4]
var finalResult = Bacon
    .fromArray(bulk)
    .flatMap(isValInCouchDb)
    .filter(onesThatExist)
    .flatMap(putValInCouchDb)

I need right after the filter to delay the whole stream by 1 second and then run putValInCouchDb Something like this really:

var bulk = array[1,2,3,4]
var finalResult = Bacon
    .fromArray(bulk)
    .flatMap(isValInCouchDb)
    .filter(onesThatExist)
    .delay(1000)
    .flatMap(putValInCouchDb)

But I think I'm missing something because .delay(1000) is delaying everything for as many seconds as there are items and then runs them all once all the time has lapsed.

Any ideas ?

UPDATE

Just to clarify based on the answer from Alex

What I would need is:

1 "filter" 1
2 "filter" 2
3 "filter" 3
4 "filter" 4
[waits 1 second]
1004 "flatMap" 1
[waits 1 second]
2004 "flatMap" 2
[waits 1 second]
3005 "flatMap" 3
[waits 1 second]
4006 "flatMap" 4

UPDATE 2 - With Solution Used

From the answer from Bergi, using .zip with an interval actually worked but what happens with .zip is that .interval creates an event every second and then each event from .interval waits for each event from my database checks. A lot of database checks happen in bulk and very fast so 'excessive buffering' occurs (which is what the bacon docs warn you).

So I decided to do it this way instead:

var bulk = array[1,2,3,4]
var finalResult = Bacon
    .fromArray(bulk)
    .flatMap(isValInCouchDb)
    .filter(onesThatExist)
    .fold([], function(a, b){ a.push(b); return a })
    .flatMap(function(a){return Bacon.sequentially(1500, a)})
    .flatMap(putValInCouchDb)

This worked nicely since folding the filtered results and sequentially creating events from them is natural, very descriptive, and without side effects.

Bacon is quite awesome

War es hilfreich?

Lösung

.delay(1000) is delaying everything for as many seconds as there are items and then runs them all once all the time has lapsed.

Yes, that's just what delay is supposed to do: take each event and fire it after a given delay.

There is no extra function that does delay and buffer at the same time, both throttle and debounce will swallow events that occured too fast.

What you can do is:

  • Use Bacon.sequentially to which you can pass the 1s-interval instead of the plain Bacon.fromArray to construct your stream
  • Use zip to join your existing event stream into events that occur at the expected time:

    Bacon.fromArray(bulk)….zip(Bacon.interval(1000), _.id)
    

I'm not sure though how your .flatMap(isValInCouchDb) manipulates the stream.

Andere Tipps

Unless you are doing something fancy in putValInCouchDb, your code appears to work exactly as you wish it would. E.g, running

var t = new Date().getTime();
function timestamp(label, x) { console.log(new Date().getTime() - t, label, x); }
var s = Bacon.fromArray([1,2,3,4])
             .filter(function(x) { timestamp("filter", x); return true })
             .delay(1000)
             .flatMap(function(x) { timestamp("flatMap", x); return Bacon.constant(x) })
s.onValue(function(x) {})

outputs something like

1 "filter" 1
2 "filter" 2
3 "filter" 3
4 "filter" 4
[waits 1 second]
1004 "flatMap" 1
1004 "flatMap" 2
1005 "flatMap" 3
1006 "flatMap" 4
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top