BehaviorSubject can not receive value with subscri

2019-08-02 06:38发布

问题:

In My Angular Application

I made several attempts to get the values using a BehaviorSubject to know when the value was changed or received. I can not get the values before loading the component.

Through this link you can see what you are returning:

https://dev.moip.com.br/v1.5/reference#listar-planos

data.service.ts:

dataOnChanged: BehaviorSubject<any> = new BehaviorSubject({});

getData() {
    return new Promise((resolve, reject) => {
        this.http.get(this.api_URL + 'plans/, this.httpOptions).subscribe((data: any) => {

            // the result is
            // data = {plans: Array(5)}

            this.dataOnChanged.next(data);
            resolve(data);
        },
            (response: any) => {
                reject(response.error);
            });
    });
}

resolve.service.ts:

constructor(
    private dataService: DataService, {
}

* Resolve
 * @param {ActivatedRouteSnapshot} route
 * @param {RouterStateSnapshot} state
 * @returns {Observable<any> | Promise<any> | any}
 */
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
    return new Promise((resolve, reject) => {
        Promise.all([
            this.dataService.getData()
        ]).then(
            () => {
                resolve();
            },
            reject
        );
    });
}

routes.module.ts:

        {
            path: 'home',
            component: HomeComponent,
            resolve: {
                data: ResolveService,
            },
        },

home.component.ts:

constructor(
    public data: DataService,
) {

    this.dataService.dataOnChanged.subscribe((result: any) => {
        // no result
        debugger;
    });

The problem is that I can not load the data returned by HTTP GET before loading the component. I need to load the data before and show the screen.

回答1:

I think the best way to get the value will be to get it from the ActivatedRoute

In your component, if you inject the ActivatedRoute:

constructor(ars: ActivatedRoute) {
  console.log(ars.snapshot.data.data) // This will log your value here
}

That way, you don't need the BehaviourSubject.

Here is an example on StackBlitz.

When you visit the /about route, it will get a value on a 2second delay to demonstrate



回答2:

Usage of BehaviorSubject is redundant over here instead you can access the resolved data using the data property of ActivatedRoute’s snapshot object or subscribe to ActivatedRoute data Property which holds the static and resolved data of the current route
it's recommended to use Observables over promises. By converting to a promise you will lose the ability to cancel a request and the ability to chain RxJS operators.

From Docs

  1. Rely on the router to call the resolver. Don't worry about all the ways that the user could navigate away. That's the router's job. Write this class and let the router take it from there.

  2. The observable provided to the Router must complete. If the observable does not complete, the navigation will not continue.

data.service.ts:

 getData():Observable<any> {
        return this.http.get(this.api_URL + 'plans/, this.httpOptions);
            }

resolve.service.ts:

import { Injectable } from '@angular/core';
    import { Resolve } from '@angular/router';
   import {Observable} from 'rxjs';

    @Injectable()
    export class resolver implements Resolve<Observable<any>> {
      constructor(private service:Service) {}

      resolve() {
        return this.dataService.getdata();
      }
    }

routes.module.ts:

 {
            path: 'home',
            component: HomeComponent,
            resolve: {
                data: resolver,
            },
        },

home.component.ts:,

  constructor( private route:ActivatedRoute) {
                 this.route.data.subscribe(value=>{
                       console.log(value);
                       });}

or

 constructor( private route:ActivatedRoute) {
                 this.item=this.route.snapshot.data;
                    console.log(this.route.snapshot.data);
                     }

STACKBLITZ DEMO