Keep list updated with Ionic 2 / Angular 2

2019-05-31 08:30发布

I have an application developed with Ionic 2 that uses Angular 2.

I want to update the list of my component in two ways.

  1. Automatic - Refresh if there is no update or if the last update was more than 30 minutes ago.
  2. Manual - If the user does not want to wait until the next update, he can update manually at any time.

When the user leaves the page cancel the automatic refresh and when he comes back re-initialize. I do not want to update immediately when the user enters the page, but only when it completes 30 minutes since the last update.

What would be the best way to achieve this? I wonder if the updates can conflict, and if yes how to cancel all and proceed only with the last call?

I'm new to Angular 2 and I'm a bit confused with the Observables. Here is what I have:

import { Component } from '@angular/core';
import { Observable } from "rxjs/Observable";
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/mergeMap';
import "rxjs/add/observable/interval";

import { NavController } from 'ionic-angular';

import { EventData } from '../../providers/event-data';

@Component({
  selector: 'page-event-list',
  templateUrl: 'event-list.html'
})
export class EventListPage {
  public events = [];
  private subscription;

  constructor(public navCtrl: NavController, public eventData: EventData) {}

  ionViewDidEnter() {
    this.load();
  }

  ionViewDidLeave() {
    this.cancel();
  }

  load() {
    let observable = Observable
      .interval(10000)
      .flatMap(() => {
        return this.eventData.load();
      })
      .share();

    this.subscription = observable
      .subscribe(events => this.events = events, error => console.log(error));

    return observable;
  }

  reload(refresher) {
    this.load()
      .subscribe(null, null, () => refresher.complete());
  }

  cancel() {
    if (this.subscription.closed) {
      return;
    }

    this.subscription.unsubscribe();
  }

}

1条回答
神经病院院长
2楼-- · 2019-05-31 09:17

You could solve this by using something like this:

// this can be a click-event, or anything else, in this case it'll just be a simple manualTrigger$.next();
let manualTrigger$ = new Rx.Subject();

// the timer will trigger immediately and then every 30seconds
let intervalTrigger$ = new Rx.Observable.timer(0, 30000);

// this is our actual combination "logic", a simple "switchMapTo"
// switchMap switches to a new subscription of our timer each time manualTrigger$ triggers and discards the old one
let resetIntervalWhenTriggeredManually$ = manualTrigger$
  .switchMapTo(intervalTrigger$);

// make sure to unsubscribe when the view is destroyed or just use the async-pipe in your template!
resetIntervalWhenTriggeredManually$
  .flatMap(makeRestCall); // here you insert your rest-call
  .subscribe(
      data => console.log("Data is:", data),
      error => console.error("Error: " + error)
  );

You can also checkout this jsbin here for a running example: http://jsbin.com/titujecuba/edit?js,console


The part where you want to automatically stop/continue the updates when the user leaves/enters the page, cannot be done with pure rxjs, you will have to keep a date somewhere of the last update and check is small periods:

// check every second
const thirtyMinutes: number = 1000 * 60 * 30;
let lastUpdated: number = -1;
let intervalTrigger$ = new Rx.Observable.timer(0, 1000);
let resetIntervalWhenTriggeredManually$ = manualTrigger$
  .do(() => lastUpdated = -1) // rest the last update to force an update
  .switchMapTo(intervalTrigger$)
  .filter(() => return +new Date() - lastUpdated >= thirtyMinutes) // only propagate dispatches if time elapsed is 30minutes
  .do(() => lastUpdate = +new Date());

resetIntervalWhenTriggeredManually$
  .flatMap(makeRestCall); // here you insert your rest-call
  .subscribe(
      data => console.log("Data is:", data),
      error => console.error("Error: " + error)
  );

And you will have to place this in a service, otherwise the state would be lost if the view is destroyed.

查看更多
登录 后发表回答