Angular2 / RxJS - 从Http observable获取数据后更新变量

时间:2016-04-11 16:20:46

标签: typescript angular

我想在数据开始从API下载时打开我的加载程序图标(例如微调器)@media only screen and (min-width: 768px) { /* tablets and desktop */ font-size: 16pt; } @media only screen and (max-width: 767px) { /* phones */ font-size: 12pt; } @media only screen and (max-width: 767px) and (orientation: portrait) { /* portrait phones */ font-size: 18pt; } ,并在成功接收时将其关闭。什么是关闭它的正确方法?

以下是我的以下代码。

我的组件:

isLoaderEnabled

我的服务:

this.isLoaderEnabled = true;
this.meetingService.getList();

谢谢。

4 个答案:

答案 0 :(得分:8)

我认为你的问题比初看起来最棘手;-)事实上,XHR不支持流式传输,所以当调用subscribe方法中注册的第一个回调时,你已经收到了所有数据。

那说XHR支持onprogress事件(请参阅此plunkr:http://plnkr.co/edit/8MDO2GsCGiOJd2y2XbQk?p=preview)。这允许获得有关下载进度的提示。 Angular2不支持此功能,但您

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
  constructor(private service:ProgressService) {}
  build(): any {
    let xhr = super.build();
    xhr.onprogress = (event) => {
      service.progressEventObservable.next(event);
    };
    return <any>(xhr);
  }
}

并使用扩展名覆盖BrowserXhr提供程序:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(BrowserXhr, { useClass: CustomBrowserXhr })
]);

进度服务可以这样实现:

export class ProgressService {
  progressEventObservable:Subject<any> = new Subject();
}

您的服务可以订阅进度服务,以便在下载实际开始时通知(即第一次为请求调用next progressEventObservable方法):

getList() {
  var subscription = this.progressService.subscribe(event => {
    if (!this.spinner) {
      this.spinner = true;
    }
  });
  this._http.get('../fake-data/someFile.json')
    .map(response => response.json())
    .do(val => this.spinner = true)
    .subscribe(
      data => {
        this.dataStore.meetingList = data;
        this.meetingListObserver.next(this.dataStore.meetingList);
      },
      err => (...),
      () => {
        this.spinner = false;
        subscription.unsubscribe();
      })
    );
}

修改

如果要在组件中使用微调器而不是服务。您可以使用专用的observable / subject,如下所述:

spinner$: Subject<boolean> = new Subject();
spinner: boolean = false;

getList() {
  var subscription = this.progressService.subscribe(event => {
    if (!this.spinner) {
      this.spinner = true;
      this.spinner$.next(this.spinner); // <-------
    }
  });
  this._http.get('../fake-data/someFile.json')
    .map(response => response.json())
    .do(val => this.spinner = true)
    .subscribe(
      data => {
        this.dataStore.meetingList = data;
        this.meetingListObserver.next(this.dataStore.meetingList);
      },
      err => (...),
      () => {
        this.spinner = false;
        this.spinner$.next(this.spinner); // <-------
        subscription.unsubscribe();
      })
    );
}

该组件可以在spinner$上订阅以获得更改通知:

@Component({
  (...)
})
export class SomeCOmponent {
  constructor(private meetingService:MeetingService) {
    this.meetingService.spinner$.subscribe((spinner) {
      this.isLoaderEnabled = spinner;
    });
  }
}

答案 1 :(得分:2)

getList() {
  this._http.get('../fake-data/someFile.json')
    .map(response => response.json())
    .do(val => this.spinner = true)
    .subscribe(
      data => {
        this.dataStore.meetingList = data;
        this.meetingListObserver.next(this.dataStore.meetingList);
      },
      err => console.log('>>>', 'Could not load meetings list. Error: ', err),
      () => this.spinner = false)
    );
}

答案 2 :(得分:1)

你需要做一些技巧才能让它正常工作:

{{1}}

答案 3 :(得分:0)

如果您的组件subscribe()转到meetingListObserver,请在订阅回调函数中将其关闭。

如果没有,请向服务添加另一个Observable或Subject,并让组件订阅它。当数据从服务返回时,请在Observable或Subject上调用next()。有关在服务中使用主题的示例,请参阅https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service