BehaviorSubject RxJs angular2

时间:2016-12-19 14:23:50

标签: angular rxjs

我没有在使用BehaviorSubject的组件中获得响应的值。我得到了它并在服务中传递它。

我在路由保护上从服务中触发HTTP。

服务:

@Injectable()
export class ProjectsService {
projects: Subject<Project[]> = new BehaviorSubject<Project[]>([]);

load(clientId: string, active: boolean): Observable<boolean> {
    return new Observable<boolean>((obs) => {
        this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId).subscribe(
            res => {
                let temp = [];
                res.forEach(a => temp.push(new Project(a)));

                if (active) this.projects.next(temp);
                else this.externalProjects.next(temp);
                obs.next(true);
                obs.complete();
            },

            err => {
                obs.next(false);
                obs.complete();
            }
        );
    });
}

成分:

ngOnInit(): void {
    // todo: check why not to load already added
    this._projectsListener = this._projectsService.projects.subscribe(a => {
        this.showIntro = a.length ? false : true;
        this.projects = a;
    });
 }

HTML:

<div class="project" [hidden]="!showIntro" *ngFor="let project of projects>
  {{project.title}}
</div>

它只是为HTTP参数设置查询参数... 后卫:

@Injectable()
export class ProjectsGuard implements CanActivate {
   constructor(
       private _projectsService: ProjectsService,
       private _router: Router) {}

   canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
       return this._projectsService.load(next.params['id'], true)
   }
}

我也尝试NgZone,但我不确定它是否正确:

load(clientId: string, active: boolean): Observable<boolean> {
    return this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId)
        .map(res => {
            let temp = res.map(a => new Project(a));

            this._ngZone.run(() => {
                console.log('temp: ', temp);
                if (active) this.projects.next(temp);
                else this.externalProjects.next(temp);
            });

            return true;
        })
        .catch(() => Observable.of(false));
}

enter image description here

1 个答案:

答案 0 :(得分:2)

首先:不要在观察者中订阅另一个观察者。相反,将其写为流:

@Injectable()
export class ProjectsService {
projects: Subject<Project[]> = new BehaviorSubject<Project[]>([]);

load(clientId: string, active: boolean): Observable<boolean> {
    return this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId)
        .map(res => {
                let temp = res.map(a => new Project(a));

                if (active) {
                    this.projects.next(temp);
                } else {
                    this.externalProjects.next(temp);
                }
                return true;
            })
       .catch(() => Observable.of(false));
}

其次:不要手动订阅无休止的流来将结果写入类成员,而是使用async - 管道:

public projects$: Observable<Project[]> = this._projectsService.projects;
public showIntro$: Observable<boolean> = this.projects$
    .map(projects => projects.length > 0);

ngOnInit(): void {
    // ...nothing to do here
}

模板:

<div class="project" [hidden]="!showIntro" *ngFor="let project of (projects$ | async)>
  {{project.title}}
</div>
....somewhere else:
<div *ngIf="showIntro$ | async">INTRO!</div>

如果您的加载问题仍然存在,那么您可能希望共享api.send方法的内容(除非确实调用它)。

一种可能性是使用在ngZone之外运行的异步方法,然后您可能需要尝试以下操作: