【问题标题】:Service class functions return undefined when i use it inside other components in Agular当我在 Angular 的其他组件中使用服务类函数时,它返回未定义
【发布时间】:2020-01-26 23:03:50
【问题描述】:

我正在使用 Angular 8。

我在服务类中创建了一个名为getUserInfo() 的函数,该函数返回有关使用云服务 Firestore 的用户的信息。

问题是,当我在服务类中显示结果时,它已定义并且可以完美运行,但在组件内部,结果是未定义的。

我想我知道错误是什么:当我在组件内部调用函数时,它返回undefined,因为该函数需要一些时间从数据库中检索数据,但我不知道如何解决它还是改用什么?

RxJS 修复了吗?

我已经尝试过路由器解析器,但也没有用。

这是我在服务类中使用的函数

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();
    }
}

【问题讨论】:

  • 你是否在组件视图中尝试过异步管道 {{ user |异步 }}
  • @Adi,是的,但它仍然给我未定义的错误

标签: angular undefined angular8 ngoninit


【解决方案1】:

我在 thisstackblitz 中重新创建了您的场景,这工作很好

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)
    })
  }
}

【讨论】:

    【解决方案2】:

    更好的方法是使用 Rxjs,因为它通常与 angular 一起使用,所以我肯定会推荐它。但是,如果您正在寻找没有它的解决方案,您可以随时使用 Promises。
    所以你面临的问题是在从服务器接收到数据之前代码正在执行。您可以通过在服务内承诺对 firestore 的调用并返回 Promise 来解决此问题,然后您可以在组件内调用 Promise。
    于是代码变成了: 服务类

    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;
            });
        }
    

    希望这会有所帮助!

    【讨论】:

    • 谢谢你uuuuuuuu
    【解决方案3】:

    简短的回答是:是的,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
        });
    }
    

    【讨论】:

    • 它给了我错误:属性订阅不存在于类型 void :(
    • 您的服务必须return 的东西,所以检查代码。如果您没有从中返回任何内容,则会发生此错误。
    • 我以前做过,但这个控制台只是为了向我显示服务内的数据,所以即使我返回数据,它也会给我我所说的错误。该控制台仅用于测试它是否有数据
    • 请提供 Stackblitz 示例,以便我们检查您的代码stackblitz.com
    • @Ferie 此代码仅在this.db.collection('users').doc(`${this.cookie.get("id")}`).ref.get(); 返回一个它可能没有执行的可观察对象时才有效。因为它不是与 Angular 的 HttpClient 模块的调用。
    【解决方案4】:
    this.user = this.authService.getUserInfo();
    

    是的,你是对的。此时,authService.getUserInfo() 尚未解决。(另外,您的 getUserInfo() 方法中没有 return 语句)。

    我可以想出两种方法来解决这个问题。

    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);
    

    Here 更多地介绍了如何将 Promise 转换为 observable。

    【讨论】:

    • 他们都没有修复它!当我添加到 this.authService.getUserInfo() 时,第一种方法给了我错误,然后说属性在类型 void 上不存在,而第二种方法我尝试了你的代码,它说同样的事情。顺便说一句,我对 RxJS 不了解 :( 所以如果没有它,我会很感激任何解决方案
    猜你喜欢
    • 2017-11-06
    • 2021-10-11
    • 2020-04-28
    • 2017-08-31
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多