javascript - 我如何告诉 Observable 我的数组已完成

标签 javascript arrays rxjs observable

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/

相关文章:

javascript - HTML5音频-Android上的currentTime值始终为0

javascript - 如何在另一个 Observable 发出时停止发出的值?

rxjs - 如何在rxjs 5中测试使用定时间隔返回可观察值的函数?

javascript - 十六进制颜色代码的按位求补能否始终返回 6 个字符?

javascript - Google Chrome 扩展,新标签焦点

java - 在 Java 中使用传递子类数组作为它们的父类

Python:按元素比较数组的最快方法

java - 类型不匹配 : cannot convert from String to int - java

Angular 5 - Promise 与 Observable - 性能上下文

javascript - 如何以 Angular 返回相互依赖的多个$http请求?