【问题标题】:Angular fetch JSON Object from API and store it in variable, check if existingAngular 从 API 获取 JSON 对象并将其存储在变量中,检查是否存在
【发布时间】:2019-06-17 00:39:24
【问题描述】:

我正在做一个 Angular 项目,并且 我有一个我没能解决的问题...

//part of class Data
constructor(private fetchData: FetchData) {
  this.subscription = timer(0, 1000000).pipe(
        switchMap(() => this.fetchData.getData())
    ).subscribe((result) => this.data = result);
}

private data: any;
private subscription: Subscription;

public getData(): Object {
    return this.data.data_property;
}

它由于运行时条件而报告错误,我想通过等待变量被填充来解决这个问题。整个应用程序都需要它,所以它非常重要。 我想用来自 Angulars rxjs 的 Observable 来解决它,但我并没有真正让它工作,我对此很陌生。 顺便说一句,FetchData 和 Data Class 都是@Injectable Services。

如果有人有额外的提示让我将变量数据转换为接口类型,例如“myData”我也会很高兴,因为我不想与任何黑客一起使用。 问题是 FetchData 的 getData 只从 HttpClient 返回一个对象:

//part of class FetchData
getData() {
    return this.http.get(this.dataUrl)
    .pipe(
        catchError(this.handleError)
      );
}  

无论如何,坦克都会提供帮助。 喜欢 Stackoverflow 社区:D

【问题讨论】:

    标签: javascript angular rxjs runtime-error observable


    【解决方案1】:

    其中一种方法可能是以下 -

    像这样设置您的数据服务 -

      export class DataService {
    
      //This is
      private _data$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
    
      data$: Observable<any>;
    
      constructor(private fetchData: FetchData) {
        this.data$ = this._data$.pipe(filter(d => !!d));
        this.getData();
       }      
    
      getData() {
    
        timer(0, 1000000).pipe(
          switchMap(() => this.fetchData.getData()),
          tap(d => {
            this._data$.next(d);
          })
        ).subscribe();
      }
    }
    

    现在要使用 DataService.data$ 在组件中执行以下操作 [在此示例中,我假设它是 HomeComponent] 您要在其中使用获取的数据 [您可以在尽可能多的组件中使用 data$ observable/服务,它会从后端发出最后获取的数据] -

    export class HomeComponent implements OnInit {
    
      constructor(private dataService: DataService) { }
    
      data$: Observable<any>;
    
      ngOnInit() {
        this.data$ = this.dataService.data$;
      }    
    }
    

    在 HomeComponent 的 html 中

    <div *ngIf="data$ | async as data">
      <!-- Render your 'data' -->
    </div>
    

    【讨论】:

    • 我的 listComponent 的构造函数看起来像这样 ``` constructor(private data: Data) { this.keyList = Object.keys(this.data.getData()); } ``` 所以必须在组件加载之前填充变量
    • 很抱歉我更正了我的代码,我以为我只是简化了我的构造函数,但它改变了很多概念。 Data 构造函数创建一个 Observable,它会在固定的时间段内更新我的数据
    • 谢谢,这对我来说似乎是最好的解决方案,因为我不想弄乱任何路由器解析器......但我有几个问题可以更好地理解,有没有办法使用超级 -输入 Observable 而不是 BehaviorSubject? “过滤器(d => !!d)”也无法正常工作,我必须导入一些东西吗?我只知道 .filter 功能......以及 tap 做什么?感谢您的帮助!!!!!真的很感激。
    • @jshAMG 是的,filter 是 rxjs 运算符。我希望它解决了你的问题。如果它解决了您的问题,我会请求将此解决方案标记为已回答,以便其他社区成员在遇到类似问题时可以利用该解决方案。
    • @jshAMG tap 又是一个 rxjs 运算符,它不使用值 [i.e.如果可观察管道中有另一个运算符,则值将按原样传递] 但您可以使用它对值执行任何操作。请参阅rxjs-dev.firebaseapp.com/api/operators/tap。我不明白您所说的“超类型 Observable”是什么意思?
    【解决方案2】:

    主要问题

    1. 如果您需要在加载应用程序之前加载一些数据app_initializer可以使用Angular: How to correctly implement APP_INITIALIZER
    2. 也许在这个片段中应该使用对类字段this.data 的引用而不是类Data 本身
    public getData(): Object {
        return this.data.data_property;
    }
    

    响应类型
    Http 方法让你提供一个泛型,像这样this.http.get&lt;CustomResponseInterface&gt;()

    【讨论】:

    • 感谢您的回答,我将阅读有关 app_initializer 的信息,第二件事是一个错误,抱歉:D 我在这里更改了我的变量以便更好地理解
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多