如何循环并更新Firebase Observable中的所有对象?

时间:2016-10-05 06:12:47

标签: angular typescript firebase firebase-realtime-database angularfire2

循环浏览可观察对象集合,更新每个对象的最佳方法是什么?

我尝试了以下方法,但是当我调用方法setActive()时,没有任何反应或者我发生了很多事情。

服务:

@Injectable()
export class ProgramService {
  private programs$: FirebaseListObservable<IProgram[]>;

  constructor(private af: AngularFire, private auth: AuthService) {
    private const path = `/programs/${auth.id}`;
    this.programs$ = af.database.list(path);
  }

  getPrograms(): Observable<IProgram[]> {
    return this.programs$;
  }

  setActive(currentProgram: IProgram) {
    console.log('setActive: ' + currentProgram.$key);
    this.programs$.map(programs => {
      programs.map(program => {
        let key = program['$key'];
        if (key === currentProgram.$key) {
          this.programs$.update(key, {"active": true});
        } else {
          this.programs$.update(key, {"active": false});
        }
      })
    })
  }
}

组件:

@Component({
  selector: 'programs',
  templateUrl: 'app/program-list.component.html'
})
export class ProgramListComponent implements OnInit {
  errorMessage: string;
  programs: IProgram[];

  constructor(
    private _ProgramService: ProgramService, 
    private _router: Router
  ) {}

  ngOnInit(): void {
    this._ProgramService.getPrograms()
      .subscribe(
        programs => this.programs = programs,
        error =>  this.errorMessage = <any>error);
  }

  setActive(program: IProgram) {
    this._ProgramService.setActive(program);
  }
}

从我的组件中,我使用programs$订阅getPrograms() observable,并列出我模板中的所有程序,并指出哪个程序是活动的。通过单击活动之外的其他行上的按钮,我会调用setActive()

模板:

<div class='panel panel-default'>
  <table class='table table-hover' *ngIf='programs && programs.length'>
    <tbody>
      <tr *ngFor='let program of programs'>
        <td (click)='gotoDetail(program)'>
          <h4 class='list-group-item-heading'>{{ program.title }}</h4>
          <p class='list-group-item-text'>{{ program.description }}</p>
        </td>
        <td class='text-right text-nowrap'>
          <button type='button' class='btn btn-success' 
              *ngIf='program.active'>Current program</button>
          <button type='button' class='btn btn-default' 
              *ngIf='!program.active' (click)='setActive(program)'>Set current</button>
        </td>
      </tr>
    </tbody>
  </table>
</div>

如果我运行上面没有任何反应。它甚至没有在我的方法中点击console.log()

如果我尝试更改方法,请说我将this.programs$.map(programs => {更改为this.programs$.forEach(programs => {,然后我从Firebase获取对象,并且更新逻辑运行良好。问题是我获得了太多数据,我得到了几个每个对象,比如这个[obj1] .. [obj1],[obj2] .. [obj1],[obj2],[obj3] .. etc,从而多次更新每个对象。下次我运行该方法时,它会在结果上加倍,第三次运行它会得到很多数据,我的浏览器会停止并放弃。

任何想法,输入,提示,技巧,建议?

1 个答案:

答案 0 :(得分:0)

我正在努力解决同样的问题。事情是从火柱返回的观察者来自金字塔&#34;方式(例如{obj1},{obj1,obj2},{obj 1,obj 2,obj 3})。

解决问题的一种原始方法是映射来自订阅的响应。注意第一个&#34;地图&#34;是rxjs地图,第二个&#34;地图&#34;是常规的es6地图。

returnMappedPrograms() : Observable { return this.programs$.map(programs => {return programs.map( (program) => {//do some thing to program..// return program}) }

虽然它解决了问题(至少在我的情况下) - 它确实过多(第二个地图在每个对象上运行几次)。我认为更好的解决方案是重建可观察的,但我仍然在研究这个问题