Loading a JSON File - using two services

#1

I want to load a json file with questions using two services:
One service opens the json file the other put the questions into an array and communicate with the components.

The idea is to have one service for data providing. Other services to real read/write data from different sources - json, database, etc. The first one uses the many other services.

The first service is QuestionService, the second service is JsonService.

But it doesn’t work :frowning:

I read the json file and can print the readed data to console. But my variable in the component don’t get the data.

Live Source/Demo: https://stackblitz.com/edit/ionic-ezx466 (maybe it don’t start with explorer/edge; try Firefox or an other browser)

#2

It’s because of async operation. Observables execute when we subscribe to it. When you subscribed, the async task was still going on and your synchronous code went ahead for execution. You can see the proof of order of execution of what got printed. Capture

Below are the changes to fix it:

In your json.service.ts

import { HttpClient } from '@angular/common/http';

public getQuestionData(): Observable<any> {
    
    return new Observable((observer) => {
      this.http.get('https://raw.githubusercontent.com/MisterChance/questionjson/master/questions.json').subscribe((response)=> {
        observer.next(response);
        observer.complete();
      });
    });
  }
constructor(private http: HttpClient) {
  }

In your questions.service.ts:

export class QuestionsService {

  questions: Question[] = [];

  public async getQuestions(): Question[] {
    await this.getQuestionData();
    return this.questions;
  }

  constructor(private http: Http, private jsonservice: JsonService) {  
  }


  async getQuestionData(){
   await this.jsonservice.getQuestionData().first().toPromise().then(data => {
      this.questions = data.questions;
      console.log(data.questions);
    }).catch((err) => {
      console.log('error in fetching questions',err);
    });
  }
}

In your home.ts

async ngOnInit() {
    this.questions = await this.questionsService.getQuestions();
    this.question = this.questions[0];
    console.log(" Count Questions: " + this.questions.length);
    //this.question = this.questions[0];
  }

Demo: https://stackblitz.com/edit/ionic-ztfuvl

#3

i assumed the problem is async, but when i use only one service (with http.get) and the component (with subscribe) it worked - that’s why i was thinking it should also work with one more service in the middle, too : component<->service2<->service1. Thank you - i will try it.

1 Like
#4

I get this error (on my PC):
error TS2339: Property ‘first’ does not exist on type ‘Observable’. in file questions.service.ts
My environment:

Angular CLI: 7.3.8
Node: 10.15.3
OS: win32 x64
Angular: 7.2.14
... common, compiler, compiler-cli, core, forms, http
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.13.8
@angular-devkit/build-angular     0.13.8
@angular-devkit/build-optimizer   0.13.8
@angular-devkit/build-webpack     0.13.8
@angular-devkit/core              7.3.8
@angular-devkit/schematics        7.3.8
@angular/cli                      7.3.8
@ngtools/webpack                  7.3.8
@schematics/angular               7.3.8
@schematics/update                0.13.8
rxjs                              6.5.1
typescript                        3.1.6
webpack                           4.29.0

In stackblitz are older versions…

#5

It works fine on the stackblitz demo I shared. Did you import first as an operator from rxjs? If issue still persists, it is most likey to deal with rxjs version’s compatibility with your angular and ionic version.

#6

I updated the versions on stackblitz. The only thing i have to change was:

public async getQuestions(): Promise< Question[ ] >

Thank you !

1 Like
#7

Great. Was this the only change or changes I mentioned including this?

#8

In Stackblitz only added Promise. No error messages - and works correct.
On my PC i added the import, too. No error message, but the radio buttons and labels disappear. (Only the last radio button without label was shown). It’s not so important - i know now that i have to learn more about Observers etc. Thank you very much !

1 Like