首页 > 解决方案 > 如何在 Angular 8+ 中迭代 RXJS 可观察对象数组 [{},{}...] 并将每个对象的属性一次推送到模板一个对象

问题描述

目标是解析一个包含 10 个对象的可观察数组,其中包含 HTML 锚属性,并一次推送一个对象(id、url、title),以填充动画模板,然后是下一个对象。

我通过 Angular 的 HTTPClient 通过 AWS API 网关从 AWS Lambda 函数中提取 JSON 数组 (JSON.stringify({results}))。

数组对象如下所示:

```
{
results: [{id: any, url: 'string', title: 'string'}, {id: any, url: 'string', title: 
'string'},...}]
}

The Template Looks Like This:

    ```
    <div class="primary" #elmRef>
      <div class="secondary" *ngFor="let anchor of (this.newsObj$ | async)" id="{{anchor.id}}">
        <a href="{{anchor.url}}">{{anchor.title}}</a>
      </div>
    </div>

架构/模型/接口如下所示:

export interface Nstream {
      id: any;
      title: string;
      link: string;
}

这是 API 服务:

loadAllNews$(): Observable<Nstream[]> {
  return this.http.get<Nstream[]>('https://example.com/stage/{proxy+}')
    .pipe(
      map(response => response['results']),
      shareReplay());
}

这是组件:

export class NewsStreamComponent implements OnInit, AfterViewInit {


  private subject = new BehaviorSubject<Nstream[]>([]);  // remembers the last array obj it emitted
  newsObjs$ = this.subject.asObservable();
  @ViewChild('elmRef', {static: false}) elmRef;

  constructor(private api: ApiService) { }

  obj$: Observable<any>;


  // onAnimationStart(event) {---TBD---}
  // onAnimationEnd(event) {---TBD---}

ngOnInit() {
    this.newsObjs$ = this.api.loadAllNews$()
      .pipe(
        map((response) => response));
  }

//  This is where I left off
ngAfterViewInit() {
  this.obj$ = this.newObjs$.pipe(
    switchMap(response => response),
      map(values => values),
    take(1));
  }
// this.obj$.subscribe(v => console.log('first instance of endpoint from object obj$: ',  v));
}

请注意:我现在最关心如何迭代和填充模板。我稍后会弄清楚动画内容,因为我提供它只是为了提供一些上下文。

目前:但是,我只能在 ngOnInit 函数内填充模板,并且所有 10 个对象都堆叠在一起,这就是我想要的(我认为)。我采用了这种方法,假设我能够遍历对象的 id,呈现一个,并使用它来切换模板上的 ngIf,从而仅在 ngAfterViewInit() 中显示具有匹配 id 的模板。经过几个多小时的尝试和搜索,我认输并寻求帮助。提前感谢您提供的任何帮助。

标签: angularaws-lambdarxjs

解决方案


好吧,你可以这样做:

ngOnInit() {
  // this will emit an observable each 500ms
  this.newsObjs$ = this.api.loadAllNews$().pipe(
    switchMap((values) => new Observable(observer => {
      if(!(values && values.length)) {
        observer.complete();
      }

      let index = 0;
      const interval = setInterval(() => {
        if(index < values.length) {
          observer.next(values[index++]);
        } else {
          observer.complete();
          clearInterval(interval);
        }
      }, 500);
    }))
  );
}

但是你为什么不使用交错动画呢?它在@angular/animations 中烘焙。


推荐阅读