【问题标题】:Angular 2 second request to Observable对 Observable 的 Angular 2 秒请求
【发布时间】:2017-02-16 07:29:28
【问题描述】:

我有一项服务,它通过 http get 请求和以下地图操作为我提供 observable。 在我的组件中,我订阅了 ngOnInit 方法中的 observable。由于我有分页功能,当用户单击分页器的另一个页面时,我想向服务发起另一个请求。我怎样才能做到这一点?我是否必须再次以新方法订阅服务,或者是否可以在组件中初始化一个 observable 以便我可以在任何方法中使用它?

export class ListItemsComponent implements OnInit {
  private _listItems = [];
  page = 1;
  constructor(private _listItemsService:ListItemsServiceService) { }

  ngOnInit() {
    this._listItemsService.getListItems (this.page)
     .subscribe(listItems => this._listItems = listItems);
  }

  pageChange(page){
     this._listItemsService.getListItems (this.page)
     .subscribe(listItems => this._listItems = listItems);
  }

}

【问题讨论】:

    标签: angular observable


    【解决方案1】:

    您的服务可以使用私有 BehaviourSubject 将 listItems$ 公开为可观察事件:

    @Injectable()
    export class ListItemsService{
        public listItems$: Observable<[]>
        private _listItems: BehaviorSubject<[]>;
    
        private dataStore: {
            listItems: []
        };
    
        constructor( @Inject(Http) private http: Http) {
            this.baseUrl = 'http://localhost/listitemservice/';
            this.dataStore = { listItems: [] };
            this._listItems = new BehaviorSubject<[]>([]);
            this.listItems$ = this._listItems.asObservable();
    
        }
        loadAll() {
           this.pageChange(1);
        }
    
        pageChange(page) {
             this.http.get(this.baseUrl  + page.id)
             .subscribe(items => {
                 this.dataStore.listItems = items;
                 this._listItems.next(items);
             });
        }
    

    然后在您的组件中,订阅 listItems$ 事件。当它触发时,将列表存储在组件类的成员变量中:

    export class ListItemsComponent implements OnInit {
      private _listItems = [];
      constructor(private _listItemsService:ListItemsServiceService) { }
    
      ngOnInit() {
        this._listItemService.listItems$.subscribe(t=> {
           this._listItems = t;
        });
        this._listItemsService.loadAll();    
      }
    
      pageChange(page){
         this._listItemsService.pageChange(page);
      }
    
    }
    

    在 pageChange 上,调用 ListItemsService 的 pageChange 方法,然后触发 listItems$ 事件。

    【讨论】:

    • 我喜欢你的方法。我有一个问题,如果用户打开一个页面并立即打开另一个页面会发生什么。由于某些原因,第一个请求将在第二个之后完成。你知道一些 rxjs 方法来“忘记”之前的请求吗?
    • 这就是 observable 的定义,不是吗?当另一个请求被触发时,一个 observable 会停止一个请求。
    • pageChange(page) { this.http.get(this.baseUrl + page.id) .subscribe(items =&gt; { this.dataStore.listItems = items; this._listItems.next(items); }); } 我认为如果你调用这个方法3次,每次新调用都不会取消之前的调用。并且所有 onSuccess 回调将在每个请求完成后触发。例如,如果您为 2 页调用它,然后为 3 页调用它,并且对 2 页​​的请求将在 3 之后完成。在用户屏幕上,我们将看到 2 页的结果。
    • @pixelbits :但是在您的示例中,您仍然在每次 pageChange 事件触发时订阅观察,对吗?我没有看到额外的价值。
    • 该值是组件之间的耦合较少。 Nikolai,你可以使用 switchMap 只接受最新的请求。
    【解决方案2】:

    如果你想避免代码重复,你可以这样做:

    export class ListItemsComponent implements OnInit {
      private _listItems = [];
      page = 1;
      constructor(private _listItemsService:ListItemsServiceService) { }
    
      ngOnInit() {
        this.pageChange(this.page);
      }
    
      subscription;
      pageChange(page){
         if(this.subscription){
             this.subscribtion.unsubscribe();
         }
    
         this.subscription = this._listItemsService.getListItems(this.page)
             .subscribe(listItems => this._listItems = listItems);
      }
    }
    

    如果您的 observable 始终使用相同的数据,并且您不想在每次订阅时都发送请求,则需要为 observable 添加缓存。例如:

    this.yourObservable
           .first()
           .publishReplay(1)
           .refCount();
    

    更多关于缓存的信息:What is the correct way to share the result of an Angular 2 Http network call in RxJs 5?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 2017-02-04
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      相关资源
      最近更新 更多