TLDR:如何判断Observed数组是否完成。例如,请参阅this jsBin。
我是Observables的新手,所以我可能会从错误的角度来看待它。鉴于下面的代码or this jsBin,我应该做些什么来让用户的网站数组“完成”。
let firstUser = {
name: 'Susan',
sites: [
{company: 'ABC Co', role: 'admin'},
{company: 'XYZ Co', role: 'reader'}
]
};
user = new Rx.BehaviorSubject(firstUser);
function authorized(authRoles) {
// check if the current user has one of the authorizedRoles roles
return this.user
.do(user => console.log("Checking user: ",JSON.stringify(user)))
.flatMap( user => user.sites )
.do(res => console.log("Mapped user roles: ",res))
.first( site => authRoles.indexOf(site.role) !== -1 ) // only return when a role matches
.do( res => console.log('First: ',res))
.map( res => true)
}
// This one finds a match and completes
authorized(['writer','admin','reader']).subscribe(res =>{
console.log("1: isAuthorized?: ",res);
}, err => {
console.log("1: ERROR: User is not authorized!");
}, () => {
console.log("1: Authorized check completed!");
});
// This one never completes
authorized(['writer','foo']).subscribe(res =>{
console.log("2: isAuthorized?: ",res);
}, err => {
console.log("2: ERROR: User is not authorized!");
}, () => {
console.log("2: Authorized check completed!");
});
请注意,(第一个)[http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-first]如果没有找到错误会抛出错误,但只有在Observable完成时才会抛出错误。
如果找到匹配,上面的内容将正确返回并完成,但是如果没有匹配则它将永远不会完成或出错,因为user.sites数组永远不会完成。
有没有办法让阵列完整?如果我首先获取/订阅用户,我可以让它工作:
//
// Pretend that fetchedUser is fetched in a safer/more sane way
// fetch the user and set it
let fetchedUser;
user.subscribe(user => fetchedUser = user);
function authorized2(authRoles) {
// check if the current user has one of the authorizedRoles roles
return Rx.Observable.of(this.fetchedUser.sites)
.do(sites => console.log("auth2: Checking users sites: ",sites))
.flatMap( sites => sites )
.do(res => console.log("Mapped user roles: ",res))
.first( site => authRoles.indexOf(site.role) !== -1 ) // only return when a role matches
.do( res => console.log('First: ',res))
.map( res => true)
}
我觉得我错过了一个关键但又简单的步骤,可以使用纯粹的Observable来实现这一点。在此先感谢您的帮助!
答案 0 :(得分:1)
Rx.Observable.of(this.fetchedUser.sites)
将其参数转换为可观察序列,然后完成。这会触发.first
运算符抛出异常。您永远不会完成this.user
主题。您可以将其更改为this.user.take(1)
甚至Rx.Observable.of(fetchedUser)
,如果您希望完成,请跳过将其设为行为主题。或者您可以将.first
更改为.map
,以便在用户未经授权时返回false。以下是使用take
运算符的示例。
const user = Rx.Observable.create((o) => {
window.setTimeout(() => {
o.next({
name: 'Susan',
sites: [
{company: 'ABC Co', role: 'admin'},
{company: 'XYZ Co', role: 'reader'}
]
});
}, 1000);
});
function authorized(authRoles) {
return user
.take(1)
.flatMap( user => user.sites )
.first( site => authRoles.indexOf(site.role) !== -1 )
.map( res => true);
}
authorized(['writer','admin','reader']).subscribe(res =>{
console.log("1: isAuthorized?: ",res);
}, err => {
console.log("1: ERROR: User is not authorized!");
}, () => {
console.log("1: Authorized check completed!");
});
authorized(['writer','foo']).subscribe(res =>{
console.log("2: isAuthorized?: ",res);
}, err => {
console.log("2: ERROR: User is not authorized!");
}, () => {
console.log("2: Authorized check completed!");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.min.js"></script>
看了你的例子后,我想知道为什么你要用RxJs来解决这个问题。 RxJs专门用于处理数据流,但您正在使用静态值。也许你的例子只是简化应用程序中实际发生的事情,但你可以在没有RxJs的情况下以同步的方式完成你的目标,而且会更加简单。这是一个例子:
function authorized(authRoles) {
return firstUser.sites.some(x => authRoles.includes(x));
}