Функции класса обслуживания возвращают неопределенное значение, когда я использую его внутри других компонентов в Agular - PullRequest
0 голосов
/ 26 сентября 2019

Я использую Angular 8.

Я создал функцию с именем getUserInfo() в классе обслуживания, которая возвращает информацию о пользователе, использующем облачный сервис Firestore.

Проблема заключается в том, чтокогда я показываю результат в классе обслуживания, он определен и работает отлично, но внутри компонента результат не определен.

Мне кажется, я знаю, в чем заключается ошибка: когда я вызываю функцию внутри компонента, он возвращает undefined, потому что функции требуется некоторое время для извлечения данных из базы данных, но я не знаю, как это исправить или что вместо этого использовать?

Исправляет ли это RxJS?

Я уже пробовал маршрутизатор Resolver, но он тоже не работал.

Это функция, которую я использую в классе обслуживания

getUserInfo() {
    this.db.collection('users').doc(`${this.cookie.get("id")}`).ref.get().then(doc => {
    return doc.data()
})}

Ниже приведен компонент, в котором я хотел быиспользовать функцию класса обслуживания:

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth/auth.service';

@Component({
    selector: 'app-super-admin',
    templateUrl: './super-admin.component.html',
    styleUrls: ['./super-admin.component.css']
})
export class SuperAdminComponent implements OnInit {
    user;
    constructor(private authService: AuthService) { }

    ngOnInit() {
        this.user = this.authService.getUserInfo();
    }
}

Ответы [ 4 ]

0 голосов
/ 26 сентября 2019

Я воссоздал ваш sceanario в этом стековом стеке, это работает отлично

util.service.ts

import { Injectable } from '@angular/core';

@Injectable()
export class UtilService {

  constructor() { }

  getUserInfo() {
    return new Promise((res,rej) => {
      this.getDelayedData((data) => {
        res(data)
      });
    });
  }

  getDelayedData(call){
   setTimeout(()=> {
     call('here your data');
    }, 1500)
  }
}

app.component.ts

import { Component } from '@angular/core';
import { UtilService } from './util.service';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  constructor(public util: UtilService) {
    this.util.getUserInfo().then((data : string) => {
      this.name = data;
      console.log(data)
    })
  }
}
0 голосов
/ 26 сентября 2019
this.user = this.authService.getUserInfo();

Да, вы правы.На данный момент, authService.getUserInfo() еще не разрешен. (Кроме того, в вашем методе getUserInfo() нет оператора return ).

Я могу придумать 2 способа решить эту проблему.

this.authService.getUserInfo().then(u => this.user = u);

Способ RxJS:

getUserInfo() {
 return from(this.db.collection('users').doc(`${this.cookie.get("id")}`).ref.get());
}

/* ... */

this.authService.getUserInfo()
 .subscribe(u => this.user = u);

Здесь больше о том, как преобразовать обещание в наблюдаемое.

0 голосов
/ 26 сентября 2019

Лучший способ - использовать Rxjs только потому, что он обычно используется с angular, поэтому я определенно рекомендую это.Однако, если вы ищете решения без него, вы всегда можете использовать Promises.
Таким образом, проблема, с которой вы сталкиваетесь, заключается в том, что код выполняется до того, как данные получены с сервера.Вы можете исправить это, пообещав свой вызов пожарному хранилищу внутри службы и вернув Обещание, тогда вы можете вызвать Обещание внутри своего компонента.
Таким образом, код становится следующим: Класс обслуживания

getUserInfo() {
let promise =  new Promise( (resolve,reject) => {
    this.db.collection('users').doc(`${this.cookie.get("id")}`).ref.get().then(doc => {
      resolve(doc.data());
    }).catch(er => {
      reject(er);
    })
}
return promise;
);

Затем вфайл компонента ts, который вы можете сделать:

   ngOnInit() {
        this.authService.getUserInfo().then(data => {
          this.user = data;
        });
    }

Надеюсь, это поможет!

0 голосов
/ 26 сентября 2019

Короткий ответ: да, RxJS решает вашу проблему.

Как вы подозреваете, ответ от сервера занимает некоторое время, чтобы вернуть что-то в ваше приложение.

Требуется ваш компонентподписаться на этот асинхронный ответ и выполнять действие, требуемое только при получении ответа.

Итак, вам нужно избавиться от Promise в вашем сервисе и просто вернуть вызов в Firebase

getUserInfo() {
    return this.db.collection('users').doc(`${this.cookie.get("id")}`).ref.get();
}

Хотя в вашем компоненте вам нужно сделать что-то вроде этого:

ngOnInit() {
    this.authService.getUserInfo().subscribe(response => {
        /* Use `response` as the answer from the server and do whatever you need to do */
        console.log(response); // Use this to inspect the response from the server
    });
}
...