Ionic2 / angular2 правильный способ использования сервиса

Я учусь создавать приложение Ionic-2, у меня есть несколько компонентов, которые потребляют службы, которые выполняют HTTP-вызов и извлекают некоторые данные, которые, в свою очередь, будут установлены в компоненте и, наконец, будут отображаться в шаблоне. Я в целом понял поток, но при кодировании делаю логическую ошибку.

Мой пример компонента:

export class FarmList {

  items: Object;

  constructor(private testService: TestService, public nav: NavController){}

  getData(): any {

    this.items = this.testService.fetchData()

  }

  nextView(){

    this.nav.push(Farm)

  }

  showDetails(id: Number){

    this.nav.push(Farm, {
      param1: id
    })

  }
}

Моя соответствующая служба:

@Injectable()
export class TestService{

    loading: boolean;
    data: Object;

    constructor(private http: Http){

        let myUrl = 'http://jsonplaceholder.typicode.com/users';

        this.loading = true;
        this.http.request(myUrl)
          .subscribe(
            (res: Response) => {

            this.loading=false;
            this.data=res.json();

          });

    }

    public fetchData(){

        return this.data;

      }
}

Снимок экрана приложения:  введите описание изображения здесь

Итак, проблема здесь:

  • Пока я не нажму кнопку Fetch (которая вызывает функцию getData () в компоненте), данные не будут загружены, так или иначе в конструкторе компонента данные должны быть установлены и не когда я вызываю getData() функцию. Я попытался написать this.items = this.testService.fetchData() эту строку в конструкторе, но это не сработало.

  • Эта проблема еще больше усугубляется, когда в другом компоненте и службе мне нужно добавить navparam, отправленный из этого компонента FarmList: let myUrl = 'http://jsonplaceholder.typicode.com/users/' + this.id ; Я пытаюсь добавить this.id, для которого установлено значение полученного navparam в его конструкторе, и я получаю undefined

    конструктор (частный nextService: NextService, navParams: NavParams) {this.id = navParams.get ("param1"); }

Я просто пытаюсь создать список на одной странице, а затем щелчок по одному из элементов списка откроет новую страницу с более подробной информацией. Я использую этот общедоступный API: http://jsonplaceholder.typicode.com/users/ и затем добавляя к нему какое-то число, чтобы получить только один объект.

Как это правильно сделать?

ОБНОВЛЕНИЕ: Я мог бы решить вторую проблему, просто получив navParams в конструкторе службы и добавив его к URL-адресу следующим образом:

@Injectable()
export class NextService{

    loading: boolean;
    data: Object;
    id: Number;

    constructor(private http: Http, navParams: NavParams){

    this.id = navParams.get("param1");
    console.log("Second service fetching param: " + this.id)

        let myUrl = 'http://jsonplaceholder.typicode.com/users/' + this.id ;
...
}

person Thinker    schedule 27.06.2016    source источник
comment
Вы пробовали использовать ngOninit?   -  person Jarod Moser    schedule 28.06.2016
comment
Нет, я не знал об этом. Есть указания, как его использовать?   -  person Thinker    schedule 28.06.2016


Ответы (1)


ngOnInit может быть тем, что вы ищете:

import { OnInit} from '@angular/core';
...
export class FarmList implements OnInit {
    ...
    ngOnInit(){
        this.getData()
    }
}

Подробнее читайте на странице angular.

РЕДАКТИРОВАТЬ:

Благодаря вашим комментариям я еще раз посмотрел на то, что делают ваши звонки. В компоненте вы устанавливаете данные, которые возвращаются из функции fetchData, которая возвращает только те данные, которые установлены в службе. В то время, когда вызывается ngOnInit, это просто пустой объект, а затем через несколько миллисекунд service.data изменяется на то, что возвращается из вашего асинхронного вызова http.

Лучше всего следовать руководству по началу работы с Http от Angular. По сути, я думаю, вы получите что-то вроде этого:

Сервис:

@Injectable()
export class TestService{
        private myUrl: string = 'http://jsonplaceholder.typicode.com/users';
// loading: boolean; 
//move any logic that has to do with UI to the component... 
//this is more of a suggestion and has to do with MV* best practices

    constructor(private http: Http){
// I think it was in John Papa's Pluralsight video on angular 2 that said
// try to do as little as possible inside of the constructor
    }    

    public fetchData(){
//the key here is to return a promise (or observable) so that the 
//component can handle it when it gets resolved
        return this.http.get(myUrl)
               .toPromise()
               .then(response => response.json().data)
      }
}

Компонент:

import { OnInit} from '@angular/core';
...
export class FarmList implements OnInit {
    ...
    ngOninit(){
        this.getData()
    }
    getData(){
        this.testService.fetchData().then(data => this.items = data)
    }
}
person Jarod Moser    schedule 27.06.2016
comment
Когда я пытаюсь реализовать Oninit, я получаю сообщение об ошибке компиляции: FarmList неправильно реализует интерфейс Oninit. Свойство ngOninit отсутствует в типе FarmList. Что это значит? Я сделал то же самое, что и вы, и сослался на документы. - person Thinker; 28.06.2016
comment
Хорошо, это было решено: вместо ngOninit () должен был быть ngOnInit (), это была опечатка. Однако список не загружался автоматически, мне все равно пришлось нажать кнопку, чтобы вызвать getData () - person Thinker; 28.06.2016
comment
В этом случае у вас есть проблемы с асинхронностью. Я сейчас отредактирую ответ - person Jarod Moser; 28.06.2016
comment
Выглядит многообещающе, но мне все равно не повезло! Первая служебная строка вызвала ошибку компиляции, поэтому я изменил ее на: myUrl: 'jsonplaceholder.typicode.com/users '; и в fetchData (): вернуть this.http.get (this.myUrl) .toPromise (). then (response = ›response.json (). data). Я сделал то, что вы предложили в компоненте, и получаю ПОЛУЧИТЬ localhost: 8100 / null 404 (не найдено) и ИСКЛЮЧЕНИЕ: Ошибка: неперехвачено (в обещании): ошибки [объект объекта]. Ответ {_body: Cannot GET / null↵, status: 404, ok: false, statusText: Ok, headers: Headers…}; - person Thinker; 29.06.2016
comment
ха-ха выглядит многообещающе, когда мы говорим об обещаниях ... Извините, измените ваше объявление myUrl на частное myUrl = 'jsonplaceholder .typicode.com / users ', когда вы опускаете http: //, он решает считать, что вы загружаете ресурс со своего базового URL, вы получали ошибки синтаксического анализа, потому что let следует использовать в функции класса для объявить переменные, и вы получили null в качестве URL-адреса из-за машинописного текста ... Я обновил ответ на свои собственные опечатки - person Jarod Moser; 29.06.2016
comment
К сожалению, я все еще получаю «undefined». В console.log (this.items) при вызове во вторых строках ngOnInit () и getData (). Я предполагаю, что служба теперь возвращает правильные данные, которые я вижу в сети. Однако назначение кажется проблемой :( - person Thinker; 29.06.2016
comment
Я выяснил ошибку: В сервисе должно быть: .then (response = ›response.json ()) - .data, который мне пришлось удалить! Большое спасибо. Этот ответ будет полезен во всех моих будущих http-запросах! - person Thinker; 29.06.2016