将流映射到延迟的promise流

时间:2014-12-26 13:03:09

标签: javascript node.js promise bacon.js

我有一个数字流,我必须使用诺言将它们变成一个帖子流。我想懒洋洋地做这件事。因此,如果我从帖子流中.take(1),它只会将一个数字转换为帖子。

这是从数字中获取帖子的承诺:

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会返回该帖子。如何使用返回promise值的惰性流?

1 个答案:

答案 0 :(得分:2)

flatMap立即获取promises创建的所有流,并立即使用所有流生成新流。直播你已经观察到这不是懒惰,并会立即调用所有承诺返回功能。

您希望一次发生一次,因此您应该使用flatMapConcat。它不是一次性地获取所有流,而是一次一个地调用它们,而不是一次调用它们 - 这是您通常期望.flatMap在其他一些FRP库中执行的操作。请注意,如果您需要一次n,请使用flatMapWithConcurrencyLimit进行概括。

以下是针对类似案例使用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