Match a stream to a lazy stream promise
I have a stream of numbers, I have to turn them into a stream of messages using a promise. And I want to do it lazily. So if I do .take(1)
from a message flow, it only turns one number into a message.
This is a promise that receives a message from among:
var getPost = function(author) {
console.log('get post' + author);
return new RSVP.Promise(function(resolve, reject) {
setTimeout(function() {
var result = "Post by " + author;
resolve(result);
}, 1000);
});
};
I'm only interested in the first post, therefore take(1)
, and it should call getPost
once.
If I use map
, the thread runs lazy calls getPost
once. If I use flatmap
, it calls getPost
for all numbers.
var lazyStream = Bacon.fromArray([1, 2, 3, 4]).map(function(value) {
return Bacon.fromPromise(getPost(value));
});
var nonLazyStream = Bacon.fromArray([1, 2, 3, 4]).flatMap(function(value) {
return Bacon.fromPromise(getPost(value));
});
lazyStream.take(2).log();
//nonLazyStream.take(2).log();
However, it map
returns the promise, but flatmap
the post itself returns. How do I have a lazy thread that returns the value of a promise?
source to share
flatMap
takes in all streams created with promises and generates a new stream using all streams at once. Live that you noticed this, not being lazy and will immediately call all the promises that return functions.
You want this to happen one at a time, so you have to use flatMapConcat
. Instead of taking all the threads at once, they will call them in turn, referencing promises sequentially - which is what you would normally expect .flatMap
to do in some other FRP libraries. Note that this summarizes the usage flatMapWithConcurrencyLimit
if you ever need to n
at a time.
Here's a use flatMapConcat
case for a similar case:
function delayPromise(val){ // delayed promise simulating an async request
return new Promise(function(resolve){
setTimeout(function(){ console.log("Resolve timeout"); resolve(val); }, 500);
});
}
var stream = Bacon.fromArray([1, 2, 3, 4]).flatMapConcat(function(value) {
return Bacon.fromPromise(delayPromise(value));
});
stream.take(1).log();
source to share