2014-12-26 1 views
3

У меня есть поток чисел, я должен превратить их в поток сообщений, используя обещание. И я хочу сделать это лениво. Поэтому, если я сделаю .take(1) из потока сообщений, он превратит только один номер в сообщение.map поток к ленивому обещанию поток

Это обещание, которое получает пост из числа:

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); 
    }); 
}; 

Я заинтересован только в первом посте, таким образом take(1) и он должен вызвать getPost один раз.

Если я использую map, поток работает ленивым, звонит getPost один раз. Если я использую flatmap, он вызывает getPost для всех номеров.

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(); 

Однако map возвращает обещание, в то время как flatMap возвращает сам пост. Как у меня есть ленивый поток, который возвращает стоимость обещания?

+0

@BenjaminGruenbaum, спасибо так много, что работает, я запутался, как/почему это работает, объяснение и/или будет принято альтернативное лучшее решение. Поскольку мне кажется, что «flatMapWithConcurrencyLimit» - побочный эффект, который решает эту проблему. – user3995789

+0

Я добавил более подробную информацию, дайте мне знать, если теперь это яснее. –

ответ

2

flatMap берет все потоки, созданные обещаниями, и порождает новый поток, используя все потоки сразу. Живи, что ты это заметил, не ленив и сразу вызовет все обещания, возвращающие функции.

Вы хотите, чтобы это происходило по одному, поэтому вы должны использовать flatMapConcat. Вместо того, чтобы сразу брать все потоки, он будет называть их по одному за один раз, вызывая обещания один за другим - это то, что вы обычно ожидаете .flatMap, чтобы делать в некоторых других FRP-библиотеках. Обратите внимание, что это обобщает использование flatMapWithConcurrencyLimit, если вам когда-либо понадобится сделать n за раз.

Вот пример использования flatMapConcat для подобного случая:

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(); 

Fiddle link