Rx.js:检查与promise异步的项目序列,直到返回true

时间:2015-06-26 21:01:18

标签: promise rxjs

我对Rx很新。我有一系列用户名,我正在对数据库进行测试,直到我找到一个不存在的用户名(一个免费的)。 db调用给了我一个承诺。

如何用rx(.js)实现它?

我实施的代码是:

用户名流

var usernamesStream = Rx.Observable.from(['user1','user2','user3'])

db查询方法

var checkUsernameIsFree = function (username) {
  return db.users.find({username:username}).toArray().then(function(users) {
    return users.length == 0
  })
}

我想我应该在promise上使用.fromPromise创建一个流。我如何实现它并加入2个流,以便只使用第一个免费用户名调用subscribe

1 个答案:

答案 0 :(得分:1)

您可以使用concatMap来保留请求的顺序,也可以隐式接受承诺:

var usernames = Rx.Observable.from(['user1','user2','user3']);

//Preserve the order of the requests
var subscription = usernames.concatMap(function(name) {
           return Rx.Observable.fromPromise(db.users.find({username:name}).toArray())
                               .filter(function(x) { return x.length == 0; })
                               .map(function() {return name; });
          })
         .first()
         .subscribe(
           function(availableUserName){
             /*Only gets called once*/
           },
           function(e){ 
             /*Will get raised if no names were found or
               there was a problem accessing the database*/
          });

根据您的要求会改变一些事情:

  1. 如果没有结果不是错误,则应使用.firstOrDefault().filter().take(1)代替。

  2. 在上面的解决方案中,concatMap可能会启动所有名称的数据库请求,并只保留响应的顺序。如果要延迟执行db请求直到上一次完成,则应使用db.users.find包裹startAsync

  3. return Rx.Observable.startAsync(function() { 
      return db.users.find({username : name}).toArray();
    });
    

    修改1

    修复了之前代码中没有将名称值传递给最终订阅者的错误。