我对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
?
答案 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*/
});
根据您的要求会改变一些事情:
如果没有结果不是错误,则应使用.firstOrDefault()
或.filter().take(1)
代替。
在上面的解决方案中,concatMap
可能会启动所有名称的数据库请求,并只保留响应的顺序。如果要延迟执行db请求直到上一次完成,则应使用db.users.find
包裹startAsync
:
return Rx.Observable.startAsync(function() {
return db.users.find({username : name}).toArray();
});
修改1
修复了之前代码中没有将名称值传递给最终订阅者的错误。