Using Observables, show the download indicator after a delay, but cancel if the download is completed on time?

In my client detail component, I have the following code that achieves what I need, but not in a reactive / observable way, I think it is possible.

Instead of wrapping this.isLoading = true;in if statements, is there a way to do this using reactive programming techniques? Perhaps by canceling / discarding the delayed observable if the client is fetched first? Or, am I going to do it wrong?

export class CustomerDetailComponent implements OnInit {

  customer: Customer;
  errorMessage: string;
  isLoading: boolean;

  constructor(
    private customerService: CustomerService,
    private route: ActivatedRoute,
    private router: Router,
    private location: Location
  ) { }

  ngOnInit() { 
    let idParam = this.route.params
      .distinctUntilChanged(params => params['id']);

    idParam.subscribe(params => 
    {
      this.errorMessage = ''; 
    });

    idParam.delay(300).subscribe(params => 
    {
      if (!(this.customer && this.customer.id == params['id']))
        this.isLoading = true;
    });

    idParam.switchMap((params: Params) => this.customerService.getCustomer(params['id']))
      .subscribe(customer => 
      { 
        this.customer = customer; 
        this.isLoading = false;
      },
      error => this.errorMessage = error);
  }
}
+4
source share
1 answer

You can write something along these lines:

function getCustomer(id) {
    return Observable.of({'name': 'John', id}).delay(500);
}

Observable.of({'id': 42})
    .distinctUntilChanged(params => params['id'])
    .do(() => {
        // this.errorMessage = '';
    })
    .switchMap((params) => {
        return Observable.combineLatest(
            Observable.of(true).delay(300).startWith(null), // delay Observable
            getCustomer(params['id']).startWith(null), // customer Observable
            function(delay, customer) { // selector function
                if (customer) {
                    return customer;
                }

                if (delay && !customer) {
                    console.log('this.isLoading = true;');
                }
                return null;
            })
            .filter(customer => customer)
            .distinctUntilChanged(customer => customer['id']);
    })
    .subscribe(
        customer => {
            console.log('this.isLoading = false;');
            console.log(customer);
            // this.customer = customer;
        },
        error => {
            // this.errorMessage = error;
        }
    );

-: https://jsbin.com/nebutup/5/edit?js,console

combineLatest() :

  • 300
  • ( )

, , . Observables .startWith(null), , , combineLatest() . , , , .

filter() null distinctUntilChanged(), , ( , ).

, , :

this.isLoading = true;
this.isLoading = false;
{ name: 'John', id: 42 }

, , .

, getCustomer() :

function getCustomer(id) {
    return Observable.of({'name': 'John', id}).delay(100);
}

:

this.isLoading = false;
{ name: 'John', id: 42 }

, .

+3

Source: https://habr.com/ru/post/1666863/


All Articles