当我在 Angular 的其他组件中使用它时,服务 class 函数 return 未定义

Service class functions return undefined when i use it inside other components in Agular

我正在使用 Angular 8.

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

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

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

RxJS 修复了吗?

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

这是我在服务中使用的功能class

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

以下是我想使用服务 class 功能的组件:

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

简短的回答是:是的,RxJS 正在解决您的问题。

如您所料,服务器的响应需要一些时间才能return 应用到您的应用程序。

您的组件需要订阅此异步应答,并且仅在收到响应时执行所需的操作。

因此,您需要摆脱服务中的 Promise,只需要 return 对 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
    });
}
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);

更多关于如何将承诺转换为可观察的。

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

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

希望对您有所帮助!

我在 this stackblitz 中重新创建了你的场景,这是 工作 很好

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