如何在 Angular2 的可观察对象中创建可观察对象

low*_*ler 5 javascript rxjs typescript angular

我可能会偏离这个过程,但这里是:

我有 Angular2 服务。该服务的数据源将是 localstorage...稍后当使用 http 返回的数据库调用时可以选择更新。因为我想要更新随着各种来源返回而返回的数据,所以看来我想使用可观察量。现在,我只是想弄清楚这个概念,所以我跳过了本地存储方面......但我包括了“背景故事”,所以它(在某种程度上)解释了我为什么想要这样做这有多种方法。

我的想法是我会有一个“getHTTPEvents()”方法,该方法将返回一个可观察对象,其有效负载是来自数据库的事件。(理论是,在未来的某个时候,我还会有一个“getLSEvents()”方法,该方法会搭载在那里)

为了模拟这一点,我有这样的代码:

private eventsUrl = 'app/mock-events.json';
getHTTPEvents() : Observable<Array<any>> { 
    return this._http.get(this.eventsUrl)
        .map(response => response.json()['events'])
        .catch(this.handleError); // handle error is a logging method
}
Run Code Online (Sandbox Code Playgroud)

我的目标是创建一种方法,允许过滤返回的事件,但仍然向服务的用户返回可观察的结果。这就是我的问题所在。为了实现这个目标,我有一个公共方法,该方法将由服务的用户调用。(尝试使用这里的模式https://coryrylan.com/blog/angular-2-observable-data-services

public getEvents(key:string,value:string) : Observable<Array<any>> {
    var allEventsObserve : Observable<Array<any>> = this.getHTTPEvents();
    var filteredEventsObserve : Observable<Array<any>>;


    allEventsObserve 
    .subscribe(
        events => {
            for(var i=0;i<events.length;i++) {
                if(events[i][key]==value) {
                    console.log('MATCH!!!' + events[i][key]); // THIS WORKS!
                    return new Observable(observer => filteredEventsObserve = observer);  // what do I need to return here?  I want to return an observable so the service consumer can get updates
                }
            }
            return allEventsObserve
        },
        error =>  console.error("Error retrieving all events for filtering: " + error));
Run Code Online (Sandbox Code Playgroud)

}

上面的方法不起作用。我观看了很多视频并阅读了很多有关可观察量的教程,但除了创建和使用 http 可观察量之外,我找不到比这更深入的内容了。

我进一步尝试了这种制作新可观察值的方法:

var newObs = Observable.create(function (observer) {
                    observer.next(events[i]);
                    observer.complete(events[i]);
                });
Run Code Online (Sandbox Code Playgroud)

虽然至少可以编译,但我不确定如何在正确的时间“返回”它......因为我无法在 allEventsObserve.subscribe 方法之外“创建”它(因为“事件”不存在)并且无法(似乎)从订阅中“返回”它。我也不完全确定如何“触发”“下一个”......?

我是否需要修改 allEventsObserve 中的数据并且仍然以某种方式返回该数据?我是否使用正确的有效负载创建一个新的可观察对象(如上面尝试的那样) - 如果是这样,我如何触发它?等等...我在这里检查过:如何在 angular2 上声明一个可观察量,但似乎无法遵循“第二个”可观察量如何被触发。也许我的整个范式都是错误的?

Nat*_*nes 3

看来您误解了 RxJS 运算符(如 、 等)实际返回的内容mapfilter我认为纠正这一点将使解决方案变得清晰。

考虑这个简短的例子:

allEventsObserve
  .map(events => {
    return 'this was an event';
  })
Run Code Online (Sandbox Code Playgroud)

诚然,这是一个非常无用的示例,因为所有数据都events丢失了,但现在让我们忽略它。上面代码的结果不是字符串数组或其他任何内容,它实际上是另一个Observable. 'this was an event'这个 Observable 只会为由 发出的每个事件数组发出字符串allEventsObserve,这使得我们能够在 observables 上链接操作符——链中的每个操作符返回一个新的Observable,它发出已经以某种方式被前一个操作符修改的项目。

allEventsObserve 
  .map(events => {
    return 'this was an event';
  }) 
  .filter(events => typeof events !== 'undefined') 
Run Code Online (Sandbox Code Playgroud)

allEventsObserve显然是 an ObservableallEventsObserve.map()计算结果为 an Observable,并且也是如此allEventsObserve.map().filter()

因此,由于您期望函数返回Observable,因此您还不想调用 subscribe ,因为这样做会返回实际上不是 的内容Observable

考虑到这一点,您的代码可以按以下方式重写:

public getEvents(key:string,value:string) : Observable<Array<any>> {
    var allEventsObserve : Observable<Array<any>> = this.getHTTPEvents();

    return allEventsObserve 
      .map(events => {
          var match = events.filter(event => event[key] == value);
          if (match.length == 0) {
            throw 'no matching event found';
          } else {
            return match[0];
          }
      })
      .catch(e => {
        console.log(e);
        return e;
      });

}
Run Code Online (Sandbox Code Playgroud)

由于getEvents返回一个Observable,因此您可以在代码中的其他地方执行类似getEvents().subscribe(events => processEvents())与它们交互之类的操作。此代码还假设this.getHTTPEvents()返回一个Observable.

另外,请注意,我将您的 for 循环更改为对 的调用filter,该调用对数组进行操作。events在本例中是一个普通的旧 JavaScript Array,因此被调用的与 RxJS 运算filter符不同。filterfilter