TLDR:如何告诉 Observed 数组完成。请参阅this jsBin例如。
我是 Observables 的新手,所以我可能从错误的 Angular 来看待这个问题。给出下面的代码,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)
}
我觉得我缺少一个关键但又简单的步骤来使用纯 Observables 来让它工作。预先感谢您的帮助!
最佳答案
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));
}
关于javascript - 我如何告诉 Observable 我的数组已完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47279663/